Synchrone toegang tot asynchroon gevalideerde opties geeft een fout

Vanaf .NET 11 RC 1 mislukt synchrone toegang tot een optiestype dat alleen asynchrone validators gebruikt, snel. In plaats van een optie-instantie zonder asynchrone validatie te retourneren, werpt het synchrone aanmaakpad een OptionsValidationException op.

Geïntroduceerde versie

.NET 11 RC 1

Vorig gedrag

Voorheen was in .NET 11 Preview 6 en Preview 7 IAsyncValidateOptions<TOptions> onafhankelijk van IValidateOptions<TOptions>. Asynchrone validators werden alleen uitgevoerd via het asynchrone opstartvalidatiepad.

Wanneer u toegang kreeg tot een asynchroon gevalideerd optietype via een synchroon aanmaaktraject, zoals IOptions<TOptions>.Value, CurrentValue, Get, IOptionsSnapshot<TOptions>.Value, Get of Create, werd de asynchrone validatie niet uitgevoerd. Het synchrone pad heeft een niet-gevalideerd exemplaar van opties geretourneerd.

Typen die IAsyncValidateOptions<TOptions> rechtstreeks implementeerden, hoefden alleen ValidateAsync te implementeren.

Nieuw gedrag

Vanaf .NET 11 RC 1 erft IValidateOptions<TOptions> over van IAsyncValidateOptions<TOptions>, en de interface is niet langer contravariant. Asynchrone validators nemen deel aan dezelfde validatieverzameling als synchrone validators.

Wanneer u toegang krijgt tot een type opties met alleen asynchrone validators via een synchroon aanmaakpad, retourneert de overgenomen Validate methode een mislukte ValidateOptionsResultmethode. Create werpt vervolgens een OptionsValidationException op. Het exceptiebericht verwijst u naar het aanroepen van ValidateOnStart en het voltooien van het opstarten voordat u synchroon toegang krijgt tot de opties.

Aangepaste typen die IAsyncValidateOptions<TOptions> rechtstreeks implementeren, moeten nu ook de overgeërfde methode Validate implementeren.

Type van brekende verandering

Deze wijziging is een gedragswijziging en kan invloed hebben op de compatibiliteit van de broncode. In een smal scenario waarin een preview-binair rechtstreeks zonder hercompilatie wordt geïmplementeerd IAsyncValidateOptions<TOptions> , kan de wijziging ook van invloed zijn op binaire compatibiliteit.

Reden voor wijziging

Validatie van asynchrone opties is geïntroduceerd in .NET 11 Preview 6 als validatiepad voor alleen opstarten. Latere ontwerpwerkzaamheden ten behoeve van validatie na het opstarten brachten een correctheidshiaat aan het licht: opties hebben ook synchrone aanmaak- en toegangspaden. Een validator die alleen de asynchrone interface heeft geïmplementeerd, kan niet worden uitgevoerd via deze synchrone paden, zodat ongeldige opties kunnen worden geretourneerd en in de cache kunnen worden opgeslagen voordat asynchrone validatie werd uitgevoerd.

Om die kloof te sluiten voordat de API een stabiele release bereikt, IAsyncValidateOptions<TOptions> is deze nu afgeleid van IValidateOptions<TOptions>. Het geïntegreerde contract behoudt één validatieverzameling, behoudt de registratievolgorde en zorgt ervoor dat niet-ondersteunde synchrone toegang mislukt met een uitzondering waarvoor actie kan worden ondernomen. Zie dotnet/runtime#131197 en het goedgekeurde API-voorstel voor meer informatie.

Voor opties die alleen asynchrone validators gebruiken, roept u ValidateOnStart aan en voltooit u het opstarten van de host voordat u synchroon toegang krijgt tot de opties:

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

await host.StartAsync();

Vermijd synchrone toegang tot opties met alleen asynchrone validators voordat het opstarten is voltooid. Deze richtlijnen zijn van toepassing op IOptions<TOptions>.Value, IOptionsMonitor<TOptions>.CurrentValue, IOptionsMonitor<TOptions>.Get, , IOptionsSnapshot<TOptions>.Value, en IOptionsSnapshot<TOptions>.Get.IOptionsFactory<TOptions>.Create

Sommige paden blijven synchroon, zelfs nadat u deze gebruikt ValidateOnStart. Opstartvalidatie initialiseert geen waarden voor latere scopes in IOptionsSnapshot<TOptions>, en IOptionsMonitor<TOptions> maakt opties synchroon opnieuw aan na een configuratiewijziging. Als u deze paden nodig hebt om te valideren, moet u ten minste één synchrone validator behouden.

Als u IAsyncValidateOptions<TOptions> rechtstreeks implementeert, voegt u de overgenomen Validate(string? name, TOptions options)-methode toe en compileert u opnieuw voor .NET 11. Retourneert ValidateOptionsResult.Skip wanneer de validator niet van toepassing is of retourneert ValidateOptionsResult.Fail wanneer synchrone validatie niet wordt ondersteund.

Als uw code gebruikmaakte van de verwijderde in TOptions-contravariantie, werk dan de betreffende toewijzingen, casts of registraties bij.

U kunt dit gedrag niet beheren met een AppContext-switch of configuratie-instelling.

Betreffende API's