非同期で検証されるオプションへの同期アクセスは例外をスローする

.NET 11 RC 1 以降では、非同期検証コントロールのみを使用するオプションの種類への同期アクセスは高速に失敗します。 非同期検証なしでオプション インスタンスを返す代わりに、同期作成パスは OptionsValidationExceptionをスローします。

導入されたバージョン

.NET 11 RC 1

以前の動作

以前は、.NET 11 Preview 6 と Preview 7 では、IAsyncValidateOptions<TOptions>はIValidateOptions<TOptions>から独立していました。 非同期検証コントロールは、非同期のスタートアップ検証パスを介してのみ実行されました。

IOptions<TOptions>.Value、CurrentValue、Get、IOptionsSnapshot<TOptions>.Value、Get、Createなどの同期作成パスを介して非同期検証オプションの種類にアクセスした場合、非同期検証コントロールは実行されませんでした。 同期パスは、未検証のオプション インスタンスを返しました。

IAsyncValidateOptions<TOptions> を直接実装した型では、ValidateAsync のみを実装する必要がありました。

新しい動作

.NET 11 RC 1 以降では、IAsyncValidateOptions<TOptions>はIValidateOptions<TOptions>から派生し、インターフェイスは反変ではなくなりました。 非同期検証コントロールは、同期検証コントロールと同じ検証コントロール コレクションに参加します。

同期作成パスを介して非同期検証コントロールのみを使用してオプション型にアクセスすると、継承された Validate メソッドは失敗した ValidateOptionsResultを返します。 Createその後、OptionsValidationExceptionを送出します。 例外メッセージは、同期的にオプションにアクセスする前に、 ValidateOnStart を呼び出して起動を完了するように指示します。

IAsyncValidateOptions<TOptions>を直接実装するカスタム型では、継承されたValidate メソッドも実装する必要があります。

破壊的変更の種類

この変更は 動作の変更 であり、 ソースの互換性に影響する可能性があります。 プレビュー バイナリが再コンパイルなしで IAsyncValidateOptions<TOptions> を直接実装する狭いシナリオでは、変更が バイナリの互換性にも影響する可能性があります。

変更理由

非同期オプションの検証は、.NET 11 Preview 6 でスタートアップ専用の検証パスとして導入されました。 スタートアップ後の検証の後の設計作業では、正確性のギャップが公開されました。オプションには、同期作成パスとアクセス パスもあります。 非同期インターフェイスのみを実装した検証コントロールは、これらの同期パスを実行できなかったため、非同期検証を実行する前に無効なオプションを返してキャッシュできます。

API が安定したリリースに到達する前にそのギャップを埋めるために、 IAsyncValidateOptions<TOptions> は IValidateOptions<TOptions>から派生するようになりました。 統合コントラクトは、1 つの検証コントロール コレクションを保持し、登録順序を保持し、サポートされていない同期アクセスをアクション可能な例外で失敗させます。 詳細については、 dotnet/runtime#131197 および 承認済みの API 提案を参照してください。

非同期検証コントロールのみを使用するオプションの場合は、同期的にオプションにアクセスする前に、 ValidateOnStart を呼び出してホストの起動を完了します。

services.AddOptions<MyOptions>()
    .Configure(o => o.Value = 42)
    .ValidateAsync(o => Task.FromResult(o.Value > 0), "Value must be positive.")
    .ValidateOnStart();

await host.StartAsync();

スタートアップが完了する前に、非同期検証コントロールのみを使用してオプションに同期アクセスしないようにします。 このガイダンスは、 IOptions<TOptions>.Value、 IOptionsMonitor<TOptions>.CurrentValue、 IOptionsMonitor<TOptions>.Get、 IOptionsSnapshot<TOptions>.Value、 IOptionsSnapshot<TOptions>.Get、および IOptionsFactory<TOptions>.Createに適用されます。

ValidateOnStartを使用した後も、一部のパスは同期的なままです。 スタートアップ検証では、後のスコープの IOptionsSnapshot<TOptions> 値はシード処理されません。 IOptionsMonitor<TOptions> は、構成の変更後にオプションを同期的に再作成します。 これらのパスを正常に検証する必要がある場合は、少なくとも 1 つの同期検証コントロールを保持します。

IAsyncValidateOptions<TOptions>を直接実装する場合は、継承されたValidate(string? name, TOptions options)メソッドを追加し、.NET 11 に対して再コンパイルします。 検証コントロールが適用されない場合は ValidateOptionsResult.Skip を返すか、同期検証がサポートされていない場合は ValidateOptionsResult.Fail を返します。

コードが削除された in TOptions 反変性に依存している場合は、影響を受ける割り当て、キャスト、または登録を更新します。

この動作は、AppContext スイッチまたは構成設定では制御できません。

影響を受ける API