Aracılığıyla paylaş


.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}Extensionsadlandı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

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;
    }
}

Yukarıdaki kodda, :AddMyLibraryService

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

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

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

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 PostConfigureistemeniz 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

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();

Ayrıca bkz.