Synchroner Zugriff auf asynchron validierte Optionen löst einen Fehler aus

Ab .NET 11 RC 1 schlägt der synchrone Zugriff auf einen Typ für Optionen, der nur asynchrone Validatoren verwendet, sofort fehl. Anstatt eine Optionsinstanz ohne asynchrone Validierung zurückzugeben, wird im synchronen Erstellungspfad ein OptionsValidationException ausgelöst.

Eingeführt in Version

.NET 11 RC 1

Bisheriges Verhalten

Zuvor war IAsyncValidateOptions<TOptions> in .NET 11 Preview 6 und Preview 7 unabhängig von IValidateOptions<TOptions>. Asynchrone Validatoren werden nur über den asynchronen Startüberprüfungspfad ausgeführt.

Wenn Sie über einen synchronen Erstellungspfad auf einen asynchron validierten Optionstyp zugegriffen haben, z. B. über IOptions<TOptions>.Value, CurrentValue, Get, IOptionsSnapshot<TOptions>.Value, Get oder Create, wurde der asynchrone Validator nicht ausgeführt. Der synchrone Pfad hat eine nicht überprüfte Optionsinstanz zurückgegeben.

Typen, die IAsyncValidateOptions<TOptions> direkt implementierten, mussten nur noch ValidateAsync implementieren.

Neues Verhalten

Ab .NET 11 RC 1 ist IAsyncValidateOptions<TOptions> von IValidateOptions<TOptions> abgeleitet, und die Schnittstelle ist nicht mehr kontravariant. Asynchrone Validatoren nehmen an derselben Validatorauflistung wie synchrone Validatoren teil.

Wenn Sie auf einen Optionstyp mit nur asynchronen Validatoren über einen synchronen Erstellungspfad zugreifen, gibt die geerbte Validate Methode einen Fehler zurück ValidateOptionsResult. Create löst dann eine OptionsValidationException aus. Die Ausnahmemeldung fordert Sie auf, ValidateOnStart aufzurufen und den Startvorgang abzuschließen, bevor Sie synchron auf die Optionen zugreifen.

Benutzerdefinierte Typen, die IAsyncValidateOptions<TOptions> direkt implementieren, müssen jetzt auch die geerbte Validate-Methode implementieren.

Art der einschneidenden Änderung

Diese Änderung ist eine Verhaltensänderung und kann sich auf die Quellkompatibilität auswirken. In einem eng begrenzten Szenario, in dem eine Vorschau-Binärdatei IAsyncValidateOptions<TOptions> direkt implementiert, ohne neu kompiliert zu werden, kann sich die Änderung auch auf die Binärkompatibilität auswirken.

Grund für die Änderung

Die asynchrone Optionsüberprüfung wurde in .NET 11 Preview 6 als Nur-Start-Überprüfungspfad eingeführt. Spätere Entwurfsarbeiten für die Überprüfung nach dem Start stellen eine Korrekturlücke offen: Optionen verfügen auch über synchrone Erstellungs- und Zugriffspfade. Ein Validator, der nur die asynchrone Schnittstelle implementiert hat, konnte diese synchronen Pfade nicht durchlaufen, sodass ungültige Optionen zurückgegeben und zwischengespeichert werden konnten, bevor die asynchrone Überprüfung ausgeführt wurde.

Um diese Lücke zu schließen, bevor die API eine stabile Veröffentlichung erreicht, leitet sich IAsyncValidateOptions<TOptions> nun von IValidateOptions<TOptions> ab. Der vereinheitlichte Vertrag verwendet eine einzige Validator-Sammlung, bewahrt die Registrierungsreihenfolge und lässt nicht unterstützten synchronen Zugriff mit einer aussagekräftigen Ausnahme fehlschlagen. Weitere Informationen finden Sie unter dotnet/runtime#131197 und dem genehmigten API-Vorschlag.

Für Optionen, die nur asynchrone Validatoren verwenden, rufen Sie ValidateOnStart auf und schließen Sie den Hoststart ab, bevor Sie synchron auf die Optionen zugreifen:

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

await host.StartAsync();

Vermeiden Sie synchronen Zugriff auf Optionen mit nur asynchronen Validatoren, bevor der Start abgeschlossen ist. Diese Anleitung gilt für IOptions<TOptions>.Value, , IOptionsMonitor<TOptions>.CurrentValue, IOptionsMonitor<TOptions>.Get, IOptionsSnapshot<TOptions>.Value, und IOptionsSnapshot<TOptions>.GetIOptionsFactory<TOptions>.Create.

Einige Pfade bleiben auch nach der Verwendung ValidateOnStartsynchron. Die Startvalidierung initialisiert keine IOptionsSnapshot<TOptions>-Werte für nachfolgende Bereiche, und IOptionsMonitor<TOptions> erstellt Optionen nach einer Konfigurationsänderung synchron neu. Wenn Sie diese Pfade zum erfolgreichen Überprüfen benötigen, behalten Sie mindestens einen synchronen Validator bei.

Wenn Sie IAsyncValidateOptions<TOptions> direkt implementieren, fügen Sie die geerbte Methode Validate(string? name, TOptions options) hinzu und kompilieren Sie sie neu für .NET 11. Geben Sie ValidateOptionsResult.Skip zurück, wenn der Validator nicht zutrifft, oder ValidateOptionsResult.Fail, wenn die synchrone Validierung nicht unterstützt wird.

Wenn Ihr Code auf der entfernten in TOptions Kontravarianz basiert, aktualisieren Sie die betroffenen Zuordnungen, Umwandlungen oder Registrierungen.

Sie können dieses Verhalten nicht mit einem AppContext-Switch oder einer Konfigurationseinstellung steuern.

Betroffene APIs