.NET kitaplığı yazarları için seçenekler desen kılavuzu
Bağımlılık ekleme yardımıyla, hizmetlerinizi ve karşılık gelen yapılandırmalarını kaydetmek seçenekler desenini kullanabilir. Seçenekler düzeni, kitaplığınızın (ve hizmetlerinizin) tüketicilerinin seçenekler sınıfınız olan TOptions
seçenek arabirimlerinin örneklerini gerektirmesini sağlar. Kesin türdeki nesneler aracılığıyla yapılandırma seçeneklerinin tüketilmesi tutarlı değer gösterimi sağlamaya yardımcı olur, veri ek açıklamalarıyla doğrulamaya olanak tanır ve dize değerlerini el ile ayrıştırma yükünü ortadan kaldırır. Kitaplığınızın tüketicilerinin kullanabileceği birçok yapılandırma sağlayıcısı vardır. Bu sağlayıcılarla tüketiciler kitaplığınızı birçok yolla yapılandırabilir.
Bir .NET kitaplığı yazarı olarak, seçenekler desenini kitaplığınızın tüketicilerine doğru şekilde gösterme hakkında genel yönergeleri öğreneceksiniz. Aynı şeyi başarmanın çeşitli yolları ve dikkat edilmesi gereken birkaç nokta vardır.
Adlandırma kuralları
Kural gereği, hizmetleri kaydetmekle sorumlu uzantı yöntemleri olarak adlandırılır Add{Service}
; burada {Service}
anlamlı ve açıklayıcı bir addır. Add{Service}
uzantı yöntemleri hem ASP.NET Core'da hem de .NET'te yaygındır.
✔️ Hizmetinizi diğer tekliflerden ayıran adlar DÜŞÜNÜN.
❌ Resmi Microsoft paketlerinden .NET ekosisteminin parçası olan adları KULLANMAYIN.
✔️ Uzantı yöntemlerini kullanıma sunan statik sınıfları olarak {Type}Extensions
adlandırmayı düşünün. Burada {Type}
, genişlettiğiniz türdür.
Ad alanı kılavuzu
Microsoft paketleri, çeşitli hizmet tekliflerinin Microsoft.Extensions.DependencyInjection
kaydını birleştirmek için ad alanını kullanır.
✔️ Paket teklifinizi net bir şekilde tanımlayan bir ad alanı DÜŞÜNÜN.
❌ Ad alanını Microsoft.Extensions.DependencyInjection
resmi olmayan Microsoft paketleri için KULLANMAYIN.
Parametresiz
Hizmetiniz çok az açık yapılandırmayla çalışabiliyorsa veya hiç açık yapılandırmayla çalışamıyorsa parametresiz bir uzantı yöntemi kullanmayı göz önünde bulundurun.
using Microsoft.Extensions.DependencyInjection;
namespace ExampleLibrary.Extensions.DependencyInjection;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMyLibraryService(
this IServiceCollection services)
{
services.AddOptions<LibraryOptions>()
.Configure(options =>
{
// Specify default option values
});
// Register lib services here...
// services.AddScoped<ILibraryService, DefaultLibraryService>();
return services;
}
}
Yukarıdaki kodda, :AddMyLibraryService
- Bir örneğini genişletir IServiceCollection
- type parametresiyle yapılan çağrılar OptionsServiceCollectionExtensions.AddOptions<TOptions>(IServiceCollection)
LibraryOptions
- Varsayılan seçenek değerlerini belirten çağrısına Configurezincirler
IConfiguration
Parametre
Birçok seçeneği tüketicilere sunan bir kitaplık yazarken, bir IConfiguration
parametre uzantısı yöntemi gerektirmeyi düşünebilirsiniz. Beklenen IConfiguration
örneğin kapsamı, işlevi kullanılarak yapılandırmanın adlandırılmış bir bölümü olarak IConfiguration.GetSection belirlenmiş olmalıdır.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ExampleLibrary.Extensions.DependencyInjection;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMyLibraryService(
this IServiceCollection services,
IConfiguration namedConfigurationSection)
{
// Default library options are overridden
// by bound configuration values.
services.Configure<LibraryOptions>(namedConfigurationSection);
// Register lib services here...
// services.AddScoped<ILibraryService, DefaultLibraryService>();
return services;
}
}
İpucu
Configure<TOptions>(IServiceCollection, IConfiguration) yöntemi NuGet paketinin Microsoft.Extensions.Options.ConfigurationExtensions
bir parçasıdır.
Yukarıdaki kodda, :AddMyLibraryService
- Bir örneğini genişletir IServiceCollection
- Parametre IConfiguration tanımlar
namedConfigurationSection
- ve öğesinin genel tür parametresini
LibraryOptions
namedConfigurationSection
ve yapılandırılan örneği geçiren çağrılar Configure<TOptions>(IServiceCollection, IConfiguration)
Bu desendeki tüketiciler, adlandırılmış bölümün kapsamlı IConfiguration
örneğini sağlar:
using ExampleLibrary.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMyLibraryService(
builder.Configuration.GetSection("LibraryOptions"));
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
çağrısı .AddMyLibraryService
türüne göre IServiceCollection yapılır.
Kitaplık yazarı olarak varsayılan değerlerin belirtilmesi size bağlı.
Not
Yapılandırmayı bir seçenek örneğine bağlamak mümkündür. Ancak ad çakışması riski vardır ve bu da hatalara neden olur. Buna ek olarak, el ile bu şekilde bağlanırken, seçenek deseninizin tüketimini bir kez okunacak şekilde sınırlandırırsınız. Bu tür tüketiciler IOptionsMonitor arabirimini kullanamayacağından, ayarlarda yapılan değişiklikler yeniden bağlanmaz.
services.AddOptions<LibraryOptions>()
.Configure<IConfiguration>(
(options, configuration) =>
configuration.GetSection("LibraryOptions").Bind(options));
Bunun yerine uzantı yöntemini kullanmanız BindConfiguration gerekir. Bu uzantı yöntemi, yapılandırmayı seçenekler örneğine bağlar ve yapılandırma bölümü için bir değişiklik belirteci kaynağı kaydeder. Bu, tüketicilerin IOptionsMonitor arabirimini kullanmasına olanak tanır.
Yapılandırma bölümü yol parametresi
Kitaplığınızın tüketicileri, temel türünüzü TOptions
bağlamak için yapılandırma bölümü yolunu belirtmek isteyebilir. Bu senaryoda, uzantı yönteminizde bir string
parametre tanımlarsınız.
using Microsoft.Extensions.DependencyInjection;
namespace ExampleLibrary.Extensions.DependencyInjection;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMyLibraryService(
this IServiceCollection services,
string configSectionPath)
{
services.AddOptions<SupportOptions>()
.BindConfiguration(configSectionPath)
.ValidateDataAnnotations()
.ValidateOnStart();
// Register lib services here...
// services.AddScoped<ILibraryService, DefaultLibraryService>();
return services;
}
}
Yukarıdaki kodda, :AddMyLibraryService
- Bir örneğini genişletir IServiceCollection
- Parametre
string
tanımlarconfigSectionPath
- Aramalar:
- AddOptions genel tür parametresiyle
SupportOptions
- BindConfiguration verilen
configSectionPath
parametreyle - ValidateDataAnnotations veri ek açıklaması doğrulamasını etkinleştirmek için
- ValidateOnStart çalışma zamanında değil, başlangıçta doğrulamayı zorlamak için
- AddOptions genel tür parametresiyle
Sonraki örnekte, veri ek açıklaması doğrulamasını etkinleştirmek için Microsoft.Extensions.Options.DataAnnotations NuGet paketi kullanılır. SupportOptions
sınıfı aşağıdaki gibi tanımlanır:
using System.ComponentModel.DataAnnotations;
public sealed class SupportOptions
{
[Url]
public string? Url { get; set; }
[Required, EmailAddress]
public required string Email { get; set; }
[Required, DataType(DataType.PhoneNumber)]
public required string PhoneNumber { get; set; }
}
Aşağıdaki JSON appsettings.json dosyasının kullanıldığını düşünün:
{
"Support": {
"Url": "https://support.example.com",
"Email": "help@support.example.com",
"PhoneNumber": "+1(888)-SUPPORT"
}
}
Action<TOptions>
Parametre
Kitaplığınızın tüketicileri, seçenekler sınıfınızın bir örneğini veren bir lambda ifadesi sağlamak isteyebilir. Bu senaryoda, uzantı yönteminizde bir Action<LibraryOptions>
parametre tanımlarsınız.
using Microsoft.Extensions.DependencyInjection;
namespace ExampleLibrary.Extensions.DependencyInjection;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMyLibraryService(
this IServiceCollection services,
Action<LibraryOptions> configureOptions)
{
services.Configure(configureOptions);
// Register lib services here...
// services.AddScoped<ILibraryService, DefaultLibraryService>();
return services;
}
}
Yukarıdaki kodda, :AddMyLibraryService
- Bir örneğini genişletir IServiceCollection
- Action<T> Parametresini
configureOptions
T
tanımlarLibraryOptions
- Eyleme göre çağrılar Configure
configureOptions
Bu desendeki tüketiciler bir lambda ifadesi (veya parametresini Action<LibraryOptions>
karşılayan bir temsilci) sağlar:
using ExampleLibrary.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMyLibraryService(options =>
{
// User defined option values
// options.SomePropertyValue = ...
});
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
Seçenekler örneği parametresi
Kitaplığınızın tüketicileri, bir inlined options örneği sağlamayı tercih edebilir. Bu senaryoda, options nesnenizin LibraryOptions
örneğini alan bir uzantı yöntemini kullanıma sunarsınız.
using Microsoft.Extensions.DependencyInjection;
namespace ExampleLibrary.Extensions.DependencyInjection;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMyLibraryService(
this IServiceCollection services,
LibraryOptions userOptions)
{
services.AddOptions<LibraryOptions>()
.Configure(options =>
{
// Overwrite default option values
// with the user provided options.
// options.SomeValue = userOptions.SomeValue;
});
// Register lib services here...
// services.AddScoped<ILibraryService, DefaultLibraryService>();
return services;
}
}
Yukarıdaki kodda, :AddMyLibraryService
- Bir örneğini genişletir IServiceCollection
- type parametresiyle yapılan çağrılar OptionsServiceCollectionExtensions.AddOptions<TOptions>(IServiceCollection)
LibraryOptions
- Verilen
userOptions
örnekten geçersiz kılınabilecek varsayılan seçenek değerlerini belirten çağrısına zincirler Configure
Bu desendeki tüketiciler, istenen özellik değerlerini satır içinde tanımlayarak sınıfının bir örneğini LibraryOptions
sağlar:
using ExampleLibrary.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMyLibraryService(new LibraryOptions
{
// Specify option values
// SomePropertyValue = ...
});
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
Yapılandırma sonrası
Tüm yapılandırma seçeneği değerleri bağlandıktan veya belirtildikten sonra, yapılandırma sonrası işlevselliği kullanılabilir. Daha Action<TOptions>
önce ayrıntılarıyla aynı parametreyi ortaya çıkarmak için öğesini çağırmayı PostConfigureseçebilirsiniz. Yapılandırma sonrası tüm .Configure
çağrıların ardından çalıştırılır. kullanmak PostConfigure
istemeniz için birkaç neden vardır:
- Yürütme sırası: Çağrılarda
.Configure
ayarlanan tüm yapılandırma değerlerini geçersiz kılabilirsiniz. - Doğrulama: Diğer tüm yapılandırmalar uygulandıktan sonra varsayılan değerlerin ayarlandığını doğrulayabilirsiniz.
using Microsoft.Extensions.DependencyInjection;
namespace ExampleLibrary.Extensions.DependencyInjection;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddMyLibraryService(
this IServiceCollection services,
Action<LibraryOptions> configureOptions)
{
services.PostConfigure(configureOptions);
// Register lib services here...
// services.AddScoped<ILibraryService, DefaultLibraryService>();
return services;
}
}
Yukarıdaki kodda, :AddMyLibraryService
- Bir örneğini genişletir IServiceCollection
- Action<T> Parametresini
configureOptions
T
tanımlarLibraryOptions
- Eyleme göre çağrılar PostConfigure
configureOptions
Bu düzendeki tüketiciler, post olmayan bir yapılandırma senaryosunda olduğu gibi bir lambda ifadesi (veya parametreyi Action<TOptions>
karşılayan Action<LibraryOptions>
bir temsilci) sağlar:
using ExampleLibrary.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMyLibraryService(options =>
{
// Specify option values
// options.SomePropertyValue = ...
});
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();