using Microsoft.Extensions.DependencyInjection; using ScadaLink.NotificationOutbox.Delivery; namespace ScadaLink.NotificationOutbox; /// /// DI registration for the Notification Outbox component: binds /// and registers the channel delivery adapters. /// public static class ServiceCollectionExtensions { /// Configuration section bound to . public const string OptionsSection = "ScadaLink:NotificationOutbox"; /// /// Registers the Notification Outbox services: the /// binding and the channel delivery adapters. /// /// This extension covers only the outbox-specific registrations. The /// reuses the /// SMTP machinery — /// Func<ISmtpClientWrapper>, OAuth2TokenService and /// NotificationOptions — so the caller (the Host on the central node) must also /// call AddNotificationService(). Re-registering those services here would /// duplicate them; relying on AddNotificationService keeps a single source of truth. /// /// is registered scoped because it /// takes a scoped /// directly. The resolves the adapters from a fresh /// scope per dispatch sweep rather than holding them, so no scoped adapter is captured by /// the singleton actor. /// public static IServiceCollection AddNotificationOutbox(this IServiceCollection services) { ArgumentNullException.ThrowIfNull(services); services.AddOptions() .BindConfiguration(OptionsSection); // Scoped: the adapter holds a scoped INotificationRepository. Registered both under // the interface (so the dispatch sweep can enumerate every channel adapter) and as // the concrete type (so callers and tests can resolve it directly). services.AddScoped(); services.AddScoped( sp => sp.GetRequiredService()); return services; } }