如何在ConfigureServices方法中获取IOptions?

LP1*_*P13 28 c# asp.net-core-mvc .net-core asp.net-core

我有asp.net核心应用程序.我想使用IOptions模式从appsettings.json注入值.所以我有一个类SecurityHeaderOptions,并且还有目标类,SecurityHeadersBuilder其构造函数IOptions<SecurityHeaderOptions>作为参数.

我知道.net核心可以在用容器注册后SecurityHeadersBuilder通过注入隐式创建实例IOptions<SecurityHeaderOptions>.

但是,我想显式创建实例SecurityHeadersBuilder,调用其方法之一,然后使用容器注册实例.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

ConfigureServices方法

public void ConfigureServices(IServiceCollection services)
{        
    services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));

    services.AddScoped<SecurityHeadersBuilder>(provider => 
           new SecurityHeadersBuilder(?????).AddDefaultPolicy())
}
Run Code Online (Sandbox Code Playgroud)

问题
1>如果我明确地将选项传递给构造函数,我是否需要SecurityHeaderOptions使用service.Configure方法注册容器?

2> Configuration.GetSection("SecurityHeaderOptions")不能返回实例IOptions<SecurityHeaderOptions>,而是返回IConfigurationSection

3>无论哪种方式,我如何检索并传递SecurityHeaderOptionsSecurityHeadersBuilder构造函数?

Qui*_*ith 30

使用.NET Core 2并且没有可用的提供程序(或关心添加它)ConfigureServices我选择使用类似的东西(使用OP代码作为示例):

public void ConfigureServices(IServiceCollection services)
{
    // secOpts available for use in ConfigureServices
    var secOpts = Configuration
        .GetSection("SecurityHeaderOptions")
        .Get<SecurityHeaderOptions>();

    ...
}
Run Code Online (Sandbox Code Playgroud)


Ror*_*ory 13

文件具体说:

不要在 中使用IOptions<TOptions>或。由于服务注册的顺序,可能存在不一致的选项状态。IOptionsMonitor<TOptions>Startup.ConfigureServices

因此,您必须以其他方式访问配置Startup.ConfigureServices,例如昆顿的回答


LP1*_*P13 7

这就是我注册期权并注入的方式 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();
    });
}
Run Code Online (Sandbox Code Playgroud)


Joã*_*ira 1

关于您的问题:

1.是的,您需要注册选项,但我相信您的做法是错误的(至少按照您的示例)。您应该这样注册:

services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));
Run Code Online (Sandbox Code Playgroud)

2.我相信我上面提到的正确注册会返回您所期望的结果。

3.只需注册它并将其放在SecurityHeaderBuilder构造函数中就足够了。注册时不需要(默认的 .NET Core IOC 容器也不允许)传递构造函数参数。为此,您需要使用其他 IOC,例如 Autofac。

但您需要注册SecurityHeadersBuilder才能在其他课程中使用它。只需使用一个接口即可。

public interface ISecurityHeadersBuilder
{
    SecurityHeadersBuilder AddDefaultPolicy();    
}

public class SecurityHeadersBuilder : ISecurityHeadersBuilder
{
    private readonly SecurityHeaderOptions _options = null;

    public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
    {
        _options = options.Value;    
    }

    public SecurityHeadersBuilder AddDefaultPolicy()
    {
        AddFrameOptions();
        AddContentSecurityPolicy();
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,只需将其注册startup.cs为这样

services.AddScoped<ISecurityHeadersBuilder, SecurityHeadersBuilder>();
Run Code Online (Sandbox Code Playgroud)