

ASP.NET Coreでオプションをappsettings.jsonから読み込んでいます。（ASPが素人です）  
使用するオプションをHTTPリクエストのパラメータにより変更したいのですが、ベストな方法はあるでしょうか？  
一応動かすことはできたのですが、改善したい点があり質問します。

例えばappsettings.jsonが、

[code]

    {
      "params":[
        "a":{
          "name": "Alice"
        },
        "b":{
          "inherit": true
        }
      ],
      "default":{
        "name": "Default"
      }
    }
    
[/code]

オプションクラスが、

[code]

    public class ExampleOptions {
      public const string Example = "Example";
      public string? Name { get; set; }
      public bool? Inherit { get; set; }
    }
    
[/code]

使用クラスが、

[code]

    public class Example {
      ExampleOptions m_options;
      public Example(IOptions<ExampleOptions> options) { /*固定じゃないのを明示するためにIOptionsSnapshotにしたい*/
        m_options = options.Value;
      }
    }
    
[/code]

登録が、

[code]

    public static IHostBuilder CreateHostBuilder(string[] arg) {
      return Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) => {
               services.AddScope(provider => {
                 return GetParamExampleOptions<ExampleOptions>(
                   hostContext.Configuration,
                   provider,
                   ExampleOptions.Example); });
             })
            .ConfigureWebHostDefaults(webBuilder => {
               webBuilder.UseStartup<Startup>();
             });
    }
    public static IOptions GetParamExampleOptions<T>(
      IConfiguration configuration, IServiceProvider provider, string sectionName) {
      var context = provider.GetRequiredService<IHttpContextAccessor>();
      var param = context.HttpContext!.GetRouteData().Values["param"] as string;
      var options = configuration.GetSection($"params:{param}:{sectionName}").Get<T>():
      var inMemoryOptions = new Dictionary<string, string>();
      //ここでInheritがtrueなら、"default"のパラメータをコピーしたインメモリオプションを生成
      //実際は複数のOptionでInheritの機能を使うため文字列操作で統一したほうが楽と思い複雑になってる
      var inheritedOptions = new ConfigurationBuilder()
        .AddInMemoryCollection(inMemoryOptions)
        .Build().GetSection($"params:{param}:{sectionName}");
      return Options.Create(inheritedOptions); /*ここでIOptionsSnapshotを作りたい*/
    }
    
[/code]

これで一応リクエストごとにオプションを変えながら動くことはできるのですが、`IOptions`ではなく`IOptionsSnapshot`を使いたいと考えています。

`servicies.AddOptions()`で登録すれば、使用側が`IOptions`でも`IOptionsSnapshot`でも自動で切り替えてくれるのですが、リクエストごとに切り替わるオプションの指定方法がわかりませんでした。

`Inherit`でDefaultオプションを継承してる機能があるため、複雑になってるかもしれません。  
同等の他の方法でもいいので、よりスマートな実装をご存じの方いらっしゃらないでしょうか？


CC BY-SA 4.0
2021-10-29T14:04:36.583
83331
2021-11-01T12:23:37.143
2021-11-01T12:23:37.143
48863
48863
question
asp.net-core
ASP.NETでHTTPリクエストごとに使用するappsettings.jsonオプションを変更するベストな方法はありますか？


IOptionsからIOptionsSnapshotに変更することはできましたので一旦解決済みとしたいと思います。

[code]

    return Options.Create(inheritedOptions); /*ここでIOptionsSnapshotを作りたい*/
    
[/code]

これを、下記のように（IOptionsと）IOptionsSnapshotの派生先であるOptionsManagerを使うようにしました。

[code]

    return new OptionsManager<T>(
        new OptionsFactory<T>(
            new IConfigureOptions<T>[]
            {
                new ConfigureOptions<T>(opt =>
                {
                    inheritedOptions.Bind(opt); /* Bind()があるのに気付いたため解決 */
                })
            },
            Enumerable.Empty<IPostConfigureOptions<T>>()
        )
    );
    
[/code]

みなさんご確認ありがとうございました。


CC BY-SA 4.0
2021-11-01T12:22:23.113
83375
2021-11-01T12:22:23.113
48863
83331
answer