Tengo la aplicación principal de asp.net. Quiero usar el patrón IOptions para inyectar valores de appsettings.json. Así que tengo una clase SecurityHeaderOptions y también tengo una clase objetivo SecurityHeadersBuilder cuyo constructor toma IOptions<SecurityHeaderOptions> como parámetro.
Sé que .net core puede crear implícitamente una instancia de SecurityHeadersBuilder inyectando IOptions<SecurityHeaderOptions> después de registrar ambos con el contenedor.
Sin embargo, quiero crear explícitamente una instancia de SecurityHeadersBuilder , llamar a uno de sus métodos y luego registrar la instancia con el contenedor.
public sealed class SecurityHeaderOptions { public string FrameOption { get; set; } public string XssProtection { get; set; } } public class SecurityHeadersBuilder { private readonly SecurityHeaderOptions _options = null; public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options) { _options = options.Value; } public SecurityHeadersBuilder AddDefaultPolicy() { AddFrameOptions(); AddConetntSecurityPolicy(); return this; } }Método ConfigureServices
public void ConfigureServices(IServiceCollection services) { services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions")); services.AddScoped<SecurityHeadersBuilder>(provider => new SecurityHeadersBuilder(?????).AddDefaultPolicy()) } Preguntas
1> Si estoy pasando opciones explícitamente al constructor, ¿necesito registrar SecurityHeaderOptions con el contenedor usando el método service.Configure ?
2> Configuration.GetSection("SecurityHeaderOptions") no puede devolver la instancia de IOptions<SecurityHeaderOptions> , sino que devuelve IConfigurationSection ?
3> De cualquier manera, ¿cómo recupero y paso SecurityHeaderOptions al constructor de SecurityHeadersBuilder ?
Al usar .NET Core 2 y no tener un proveedor disponible (o querer agregarlo) en ConfigureServices , opté por algo como esto (usando el código OP como ejemplo):
public void ConfigureServices(IServiceCollection services) { // secOpts available for use in ConfigureServices var secOpts = Configuration .GetSection("SecurityHeaderOptions") .Get<SecurityHeaderOptions>(); ... }Así es como registro opciones y las inyecto en SecurityHeadersBuilder
public void ConfigureServices(IServiceCollection services) { services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions")); services.AddScoped<SecurityHeadersBuilder>(provider => { var option = provider.GetService<IOptions<SecurityHeaderOptions>>(); return new SecurityHeadersBuilder(option) .AddDefaultPolicy(); }); }Los documentos dicen específicamente:
No use
IOptions<TOptions>oIOptionsMonitor<TOptions>enStartup.ConfigureServices. Puede existir un estado de opciones inconsistente debido al orden de los registros de servicio.
Por lo tanto, deberá acceder a la configuración de alguna otra manera desde Startup.ConfigureServices , por ejemplo, la respuesta de Quinton