using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Options = RAIC.Extensions.Configuration.EntityFrameworkCore.SqlServer.SqlServerNotificationConfigurationReloaderOptions; namespace RAIC.Extensions.Configuration.EntityFrameworkCore.SqlServer.Extensions; public static class ServiceCollectionExtensions { /// /// Adds (a implementation) /// and supporting services to the , obtaining its connection string from a instance. /// /// Type of the which implements /// Concrete type which implements /// The service collection to add the services too /// The service collection it was called on now with added services /// If your connection string contains a password then this method may not work, please use another overload /// If your does not have a connection string public static IServiceCollection AddSqlServerNotificationConfigurationReloadService(this IServiceCollection services) where TDbContext : DbContext, ISettingsDbContext, TSetting> where TSetting : class, ISetting { var optionsBuilder = services.AddCoreServices(); optionsBuilder.Configure((options, dependency) => { options.ConnectionString = dependency.Database.GetConnectionString() ?? throw new NullReferenceException($"{typeof(TDbContext).Name} ConnectionString is null"); }); return services; } /// /// Adds (a implementation) /// and supporting services to the . /// /// Type of the which implements /// Concrete type which implements /// The service collection to add the services too /// /// Action to manually configure the instance consumed by eg. /// /// options => { /// options.ConnectionString = context.Configuration.GetConnectionString("Default"); /// } /// /// /// The service collection it was called on now with added services public static IServiceCollection AddSqlServerNotificationConfigurationReloadService(this IServiceCollection services, Action configure) where TDbContext : DbContext, ISettingsDbContext, TSetting> where TSetting : class, ISetting { var optionsBuilder = services.AddCoreServices(); optionsBuilder.Configure(configure); return services; } private static OptionsBuilder AddCoreServices(this IServiceCollection services) where TDbContext : DbContext, ISettingsDbContext, TSetting> where TSetting : class, ISetting { services.AddSingleton(static provider => { var configRoot = (IConfigurationRoot)provider.GetRequiredService(); // DEBT: Is this cast always safe? return configRoot.Providers.OfType().Single(); }); return services.AddHostedService>() .AddOptions().ValidateDataAnnotations().ValidateOnStart(); } }