.NET9でのOptionsの使用

選択肢パターンは、ASP.NET Coreでクラスを使用して関連する設定の厳密な型指定アクセスを提供します。設定を個別のクラスに分離することで、アプリケーションはカプセル化と関心分離の原則を遵守します。カプセル化は、設定に依存するクラスがその使用する設定にのみ依存することを保証し、関心分離はアプリケーションの異なる部分の設定が相互に独立していることを保証します。さらに、選択肢パターンは設定データの検証メカニズムも提供します。

### 三種類のIOptions:

以下はコードファイルです：

#### Program.cs

```csharp
using Microsoft.Extensions.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOptions<Setting>().BindConfiguration("Setting");

var app = builder.Build();

app.Services.GetService<IOptionsMonitor<Setting>>()?.OnChange((setting, name) =>
{
    app.Logger.LogInformation(setting.Value);
});

app.MapGet("/opt1", (IOptions<Setting> option) =>
{
    app.Logger.LogInformation("opt1");
    return option.Value;
});

app.MapGet("/opt2", (IOptionsSnapshot<Setting> option) =>
{
    app.Logger.LogInformation("opt2");
    return option.Value;
});

app.MapGet("/opt3", (IOptionsMonitor<Setting> option) =>
{
    app.Logger.LogInformation("opt3");
    return option.CurrentValue;
});

app.Run();

class Setting
{
    public string Name { get; set; }
    public string Value { get; set; }
}
```

#### appsettings.json

```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Setting": {
    "Name": "key",
    "Value": "1234567890"
  }
}
```

#### OptionDemo.http

```http
@OptionDemo_HostAddress = http://localhost:5064

GET {{OptionDemo_HostAddress}}/opt1
Accept: application/json

###

GET {{OptionDemo_HostAddress}}/opt2
Accept: application/json

###

GET {{OptionDemo_HostAddress}}/opt3
Accept: application/json

###
```

OptionDemo.httpを開き、Opt1、Opt2、Opt3の「リクエストを送信」をクリックすると、結果は以下の通りです。

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZG2UbnaMzlMDajiaoNnSRicx526AKktAh5EvOD8SKuTq9q98GQboLrM7w/640?wx_fmt=png&from=appmsg)

appsettings.jsonのSettingのValueを「1234567890ABCD」に変更すると、結果は以下の通りです。

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZicZGDEoSrodiaQnRQ9mbLoWTTUaADZ3kdTdYJ044kXia2haSp4nH3gyAA/640?wx_fmt=png&from=appmsg)

**リクエストOpt1結果：**

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZDULKr5LEYqIYqic6ludia7LDH99icqOMKbcufcWQFP8rTz5Ts9V2GECXw/640?wx_fmt=png&from=appmsg)

**リクエストOpt2結果：**

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZTs0Wr2iajWlvGKggJuIRmPicHOT0ON3fVYpFuQEMB8OLazLBJo4NgUuw/640?wx_fmt=png&from=appmsg)

**リクエストOpt3結果：**

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZD0xRRxhIe4kWibwR4Yl9Ako1aX4ngUFGc45my7SVLPDYLicenPTFL2xA/640?wx_fmt=png&from=appmsg)

### 検証：

Optionsを検証するには、Validate()メソッドを利用できます。現在、2つの検証ポイントがあります。1つはサービスの起動時で、ValidateOnStartメソッドがあります。もう1つは、このOptionsを使用する時で、ValidateOnStartメソッドを書かない場合です。

```csharp
builder.Services.AddOptions<Setting>()
    .BindConfiguration("Setting")
    .ValidateOnStart<Setting>()
    .Validate(setting =>
    {
        return !string.IsNullOrWhiteSpace(setting.Name) && !string.IsNullOrWhiteSpace(setting.Value);
    }, "Setting設定エラー");
```

発生するエラーメッセージは以下の通りです。

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZDy9D5EPZBhD4UP1lQzxBAoxUOcnSb2UiaJib8VJUo4ugccobYP7R7Rjw/640?wx_fmt=png&from=appmsg)

Validateを用いるとカスタム検証になりますが、もちろんDataAnnotationsを利用して検証することも可能です。コードは以下の通りです。

```csharp
builder.Services.AddOptions<Setting>()
    .BindConfiguration("Setting")
    .ValidateDataAnnotations();
```

発生するエラーメッセージは以下の通りです。

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCecZ1M4p0gwnzALPQAdt5ZFSMjiaIb2tXmLic5icY1V1bI942Mv4H8YZOV8bV45U8rg1xvtzVPYd4Ug/640?wx_fmt=png&from=appmsg)

(Translated by GPT)