Akses sinkron ke opsi yang divalidasi secara asinkron menimbulkan error

Mulai dari .NET 11 RC 1, akses sinkron ke jenis opsi yang hanya menggunakan validator asinkron gagal dengan cepat. Alih-alih mengembalikan instans opsi tanpa validasi asinkron, jalur pembuatan sinkron memunculkan OptionsValidationException.

Versi yang diperkenalkan

.NET 11 RC 1

Perilaku sebelumnya

Sebelumnya, dalam .NET 11 Pratinjau 6 dan Pratinjau 7, IAsyncValidateOptions<TOptions> bersifat independen dari IValidateOptions<TOptions>. Validator asinkron hanya berjalan melalui jalur validasi startup asinkron.

Saat Anda mengakses jenis opsi yang divalidasi asinkron melalui jalur pembuatan sinkron, seperti IOptions<TOptions>.Value, , CurrentValue, GetIOptionsSnapshot<TOptions>.Value, Get, atau Create, validator asinkron tidak berjalan. Jalur sinkron mengembalikan instans opsi yang tidak valid.

Tipe yang langsung mengimplementasikan IAsyncValidateOptions<TOptions> hanya perlu mengimplementasikan ValidateAsync.

Perilaku baru

Mulai dari .NET 11 RC 1, IAsyncValidateOptions<TOptions> berasal dari IValidateOptions<TOptions>, dan antarmuka tidak lagi kontravarian. Validator asinkron berpartisipasi dalam koleksi validator yang sama dengan validator sinkron.

Saat Anda mengakses tipe opsi yang hanya memiliki validator asinkron melalui jalur pembuatan sinkron, metode turunan Validate mengembalikan ValidateOptionsResult yang gagal. Createkemudian melempar .OptionsValidationException Pesan pengecualian mengarahkan Anda untuk memanggil ValidateOnStart dan menyelesaikan startup sebelum Anda mengakses opsi secara sinkron.

Tipe kustom yang menerapkan IAsyncValidateOptions<TOptions> secara langsung sekarang juga harus menerapkan metode turunan Validate.

Jenis perubahan yang memutus kompatibilitas

Perubahan ini adalah perubahan perilaku dan dapat memengaruhi kompatibilitas sumber. Dalam skenario sempit di mana biner pratinjau langsung diterapkan IAsyncValidateOptions<TOptions> tanpa kompilasi ulang, perubahan juga dapat memengaruhi kompatibilitas biner.

Alasan perubahan

Validasi opsi asinkron diperkenalkan di .NET 11 Pratinjau 6 sebagai jalur validasi khusus startup. Kemudian pekerjaan desain untuk validasi pasca-startup mengekspos kesenjangan kebenaran: Opsi juga memiliki jalur pembuatan dan akses yang sinkron. Validator yang hanya menerapkan antarmuka asinkron tidak dapat berjalan melalui jalur sinkron tersebut, sehingga opsi yang tidak valid dapat dikembalikan dan di-cache sebelum validasi asinkron berjalan.

Untuk menutup celah itu sebelum API mencapai rilis yang stabil, IAsyncValidateOptions<TOptions> sekarang berasal dari IValidateOptions<TOptions>. Kontrak terpadu menyimpan satu koleksi validator, mempertahankan pesanan pendaftaran, dan membuat akses sinkron yang tidak didukung gagal dengan pengecualian yang dapat ditindaklanjuti. Untuk informasi selengkapnya, lihat dotnet/runtime#131197 dan proposal API yang disetujui.

Untuk opsi yang hanya menggunakan validator asinkron, panggil ValidateOnStart dan selesaikan startup host sebelum Anda mengakses opsi secara sinkron:

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

await host.StartAsync();

Hindari mengakses opsi secara sinkron yang hanya memiliki validator asinkron sebelum proses startup selesai. Panduan ini berlaku untuk IOptions<TOptions>.Value, , IOptionsMonitor<TOptions>.CurrentValueIOptionsMonitor<TOptions>.Get, IOptionsSnapshot<TOptions>.Value, IOptionsSnapshot<TOptions>.Get, dan IOptionsFactory<TOptions>.Create.

Beberapa jalur tetap sinkron bahkan setelah Anda menggunakan ValidateOnStart. Validasi saat startup tidak menginisialisasi nilai IOptionsSnapshot<TOptions> untuk cakupan selanjutnya, dan IOptionsMonitor<TOptions> membuat ulang opsi secara sinkron setelah perubahan konfigurasi. Jika Anda memerlukan jalur tersebut agar berhasil divalidasi, simpan setidaknya satu validator sinkron.

Jika Anda menerapkan IAsyncValidateOptions<TOptions> secara langsung, tambahkan metode yang diwariskan Validate(string? name, TOptions options) dan kompilasi ulang terhadap .NET 11. Mengembalikan ValidateOptionsResult.Skip ketika validator tidak berlaku, atau mengembalikan ValidateOptionsResult.Fail saat validasi sinkron tidak didukung.

Jika kode Anda bergantung pada kontravariansi yang dihapus in TOptions , perbarui tugas, transmisi, atau pendaftaran yang terpengaruh.

Anda tidak dapat mengontrol perilaku ini dengan sakelar AppContext atau pengaturan konfigurasi.

API yang Terpengaruh