Based on @pfx answer
I've improved a little bit adding also the IOptionsMonitor
Create a AppSettingsExtensions.cs class:
public static class AppSettingsExtensions
{
public static TAppSettings AddAppSettings<TAppSettings>(this IServiceCollection services,
IConfiguration configuration, string sectionName = "AppSettings",
ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TAppSettings : class
{
var appSettingsSection = configuration.GetSection(sectionName);
var appSettings = appSettingsSection.Get<TAppSettings>();
if (appSettings == null) throw new NullReferenceException(nameof(appSettings));
services.Configure<TAppSettings>(appSettingsSection);
services.Add(new ServiceDescriptor(typeof(TAppSettings), serviceProvider => appSettings, lifetime));
return appSettings;
}
public static TAppSettings AddAppSettings<TAppSettings>(this IServiceCollection services, IConfiguration configuration,
TAppSettings appSettings,
Func<IEnumerable<IOptionsChangeTokenSource<TAppSettings>>> optionsChangeTokenSourceBuilder = null,
ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TAppSettings : class
{
if (appSettings == null) throw new NullReferenceException(nameof(appSettings));
var appSettingsConfigureOptions = configuration.CreateAppSettingsConfigureOptions<TAppSettings>();
appSettingsConfigureOptions.Configure(appSettings);
var appSettingsOptions = Options.Create(appSettings);
var appSettingsMonitor = AddAppSettingsMonitor(services, configuration, appSettingsConfigureOptions);
services.Add(appSettingsOptions,lifetime);
services.Add(appSettingsMonitor, lifetime);
return appSettings;
}
private static IOptionsMonitor<TAppSettings> AddAppSettingsMonitor<TAppSettings>(IServiceCollection services,
IConfiguration configuration, ConfigureFromConfigurationOptions<TAppSettings> appSettingsConfigureOptions)
where TAppSettings : class
{
var appSettingsOptionsFactory = services.CreateAppSettingsOptionsFactory(appSettingsConfigureOptions);
var appSettingsMonitor = new OptionsMonitor<TAppSettings>(appSettingsOptionsFactory,
configuration.CreateAppSettingsOptionsChangeTokenSources<TAppSettings>(), new OptionsCache<TAppSettings>());
return appSettingsMonitor;
}
private static IEnumerable<IOptionsChangeTokenSource<TAppSettings>> CreateAppSettingsOptionsChangeTokenSources<TAppSettings>(this IConfiguration configuration,
Func<IEnumerable<IOptionsChangeTokenSource<TAppSettings>>> builder=null) where TAppSettings : class
{
return builder?.Invoke()??Enumerable.Empty<IOptionsChangeTokenSource<TAppSettings>>();
}
public static ConfigureFromConfigurationOptions<TAppSettings> CreateAppSettingsConfigureOptions<TAppSettings>(this IConfiguration configuration) where TAppSettings : class
{
return new ConfigureFromConfigurationOptions<TAppSettings>(configuration);
}
public static OptionsFactory<TAppSettings> CreateAppSettingsOptionsFactory<TAppSettings>(this IServiceCollection services,ConfigureFromConfigurationOptions<TAppSettings> appSettingsConfigureOptions) where TAppSettings : class
{
return new OptionsFactory<TAppSettings>(new[] {appSettingsConfigureOptions},
Enumerable.Empty<IPostConfigureOptions<TAppSettings>>());
}
}
Create a DependencyInjectionExtensions.cs class:
public static class DependencyInjectionExtensions
{
public static void Add<TService>(
this IServiceCollection services,
ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
where TService : class
{
switch (serviceLifetime)
{
case ServiceLifetime.Singleton:
services.AddSingleton<TService>();
break;
case ServiceLifetime.Scoped:
services.AddScoped<TService>();
break;
case ServiceLifetime.Transient:
services.AddTransient<TService>();
break;
default:
throw new ArgumentOutOfRangeException(nameof(serviceLifetime), (object) serviceLifetime, null);
}
}
public static void Add<TService, TImplementation>(
this IServiceCollection services,
ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
where TService : class
where TImplementation : class, TService
{
switch (serviceLifetime)
{
case ServiceLifetime.Singleton:
services.AddSingleton<TService, TImplementation>();
break;
case ServiceLifetime.Scoped:
services.AddScoped<TService, TImplementation>();
break;
case ServiceLifetime.Transient:
services.AddTransient<TService, TImplementation>();
break;
default:
throw new ArgumentOutOfRangeException(nameof(serviceLifetime), (object) serviceLifetime, null);
}
}
public static void Add<TService>(
this IServiceCollection services,
TService service,
ServiceLifetime serviceLifetime = ServiceLifetime.Singleton)
where TService : class
{
switch (serviceLifetime)
{
case ServiceLifetime.Singleton:
services.AddSingleton<TService>(service);
break;
case ServiceLifetime.Scoped:
services.AddScoped<TService>((Func<IServiceProvider, TService>) (_ => service));
break;
case ServiceLifetime.Transient:
services.AddTransient<TService>((Func<IServiceProvider, TService>) (_ => service));
break;
default:
throw new ArgumentOutOfRangeException(nameof(serviceLifetime), (object) serviceLifetime, null);
}
}
}
I know that there's a lot going on here, but my goal was to provide a library to help resolving common code between projects, this way I could simplify some dependency injection code.
Hope it helps, and please feel free to make suggestions to this code, I'll be trully grateful to make those extensions even better