web-dev-qa-db-ja.com

ConfigureServicesメソッドでIOptionsを取得する方法は?

Asp.netコアアプリケーションがあります。 IOptionsパターンを使用して、appsettings.jsonから値を注入します。クラスSecurityHeaderOptionsがあり、コンストラクターが_IOptions<SecurityHeaderOptions>_をパラメーターとして取るターゲットクラスSecurityHeadersBuilderもあります。

.netコアは、コンテナに両方を登録した後に_IOptions<SecurityHeaderOptions>_を挿入することにより、SecurityHeadersBuilderのインスタンスを暗黙的に作成できることを知っています。

ただし、SecurityHeadersBuilderのインスタンスを明示的に作成し、そのメソッドの1つを呼び出して、インスタンスをコンテナに登録します。

_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;
    }
}
_

ConfigureServicesメソッド

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

    services.AddScoped<SecurityHeadersBuilder>(provider => 
           new SecurityHeadersBuilder(?????).AddDefaultPolicy())
}
_

質問
1>オプションをコンストラクタに明示的に渡す場合、_service.Configure_メソッドを使用してSecurityHeaderOptionsをコンテナに登録する必要がありますか?

2> Configuration.GetSection("SecurityHeaderOptions")は_IOptions<SecurityHeaderOptions>_のインスタンスを返すことができず、代わりにIConfigurationSection?を返しますか?

3>どちらの方法でも、SecurityHeaderOptionsを取得してSecurityHeadersBuilderのコンストラクターに渡すにはどうすればよいですか?

26
LP13

.NET Core 2を使用し、ConfigureServicesでプロバイダーを利用できない(または追加することを気にしない)ので、次のようなものを選択しました(例としてOPコードを使用)。

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

    ...
}
25
Quinton Smith

これは、オプションを登録し、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();
    });
}
7
LP13

あなたの質問について:

1。はい、オプションを登録する必要がありますが、間違った方法で行っていると思います(少なくともあなたの例では)。これとして登録する必要があります。

services.Configure<SecurityHeaderOptions>(options => Configuration.GetSection("SecurityHeaderOptions").Bind(options));

2。上記の正しい登録は、あなたが期待しているものを返すと信じています。

登録してSecurityHeaderBuilderコンストラクターに配置するだけで十分です。登録時にコンストラクタパラメータを渡す必要はありません(デフォルトの.NET Core IOC container allow)も必要ありません。そのためには、Autofacなどの他のIOCを使用する必要があります。

ただし、他のクラス内で使用するには、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;
    }
}

次に、これをstartup.csに登録するだけです

services.AddScoped<ISecurityHeadersBuilder, SecurityHeadersBuilder>();
1
João Pereira