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; }
}