using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Svrnty.CQRS.Events.Abstractions.Sagas; namespace Svrnty.CQRS.Events.Sagas; /// /// Service collection extensions for saga orchestration. /// public static class SagaServiceCollectionExtensions { /// /// Add saga orchestration infrastructure. /// /// The service collection. /// Use in-memory state store (default: true). /// The service collection for chaining. public static IServiceCollection AddSagaOrchestration( this IServiceCollection services, bool useInMemoryStateStore = true) { if (services == null) throw new ArgumentNullException(nameof(services)); // Register core services services.TryAddSingleton(); services.TryAddSingleton(); // Register state store if (useInMemoryStateStore) { services.TryAddSingleton(); } return services; } /// /// Register a saga definition. /// /// The saga type. /// The service collection. /// The saga name. /// Action to configure saga definition. /// The service collection for chaining. public static IServiceCollection AddSaga( this IServiceCollection services, string sagaName, Action configure) where TSaga : class, ISaga { if (services == null) throw new ArgumentNullException(nameof(services)); if (string.IsNullOrWhiteSpace(sagaName)) throw new ArgumentException("Saga name cannot be null or empty", nameof(sagaName)); if (configure == null) throw new ArgumentNullException(nameof(configure)); // Register saga type services.TryAddTransient(); // Create and configure definition var definition = new SagaDefinition(sagaName); configure(definition); // Register definition with registry services.AddSingleton(sp => { var registry = sp.GetRequiredService(); registry.Register(definition); return new SagaRegistration(sagaName); }); return services; } } /// /// Marker interface for saga registration tracking. /// internal interface ISagaRegistration { string SagaName { get; } Type SagaType { get; } } /// /// Saga registration marker. /// internal sealed class SagaRegistration : ISagaRegistration where TSaga : ISaga { public SagaRegistration(string sagaName) { SagaName = sagaName ?? throw new ArgumentNullException(nameof(sagaName)); SagaType = typeof(TSaga); } public string SagaName { get; } public Type SagaType { get; } }