Megosztás a következőn keresztül:


A beállításminta útmutatója .NET-kódtár-szerzőknek

A függőséginjektálás segítségével a szolgáltatások és a hozzájuk tartozó konfigurációk regisztrálása kihasználhatja a beállítási mintát. A beállításminta lehetővé teszi a tár (és a szolgáltatások) felhasználói számára, hogy olyan beállítási felületpéldányokat követeljenek meg, ahol TOptions a beállítások osztálya található. A konfigurációs beállítások erősen gépelt objektumokon keresztül történő használata segít a konzisztens értékmegjelenítés biztosításában, lehetővé teszi az adatjegyzetekkel való ellenőrzést, és megszünteti a sztringértékek manuális elemzésének terhét. A tár felhasználói számos konfigurációs szolgáltatót használhatnak. Ezekkel a szolgáltatókkal a felhasználók sokféleképpen konfigurálhatják a tárat.

.NET-kódtár-szerzőként általános útmutatást kaphat arról, hogyan teheti elérhetővé a beállítási mintát a tár felhasználói számára. Többféleképpen is el lehet érni ugyanazt a dolgot, és több szempontot is figyelembe kell venni.

Elnevezési konvenciók

Konvenció szerint a szolgáltatások regisztrálásáért felelős bővítménymetelyeket nevezik el Add{Service}, ahol {Service} értelmezhető és leíró nevet adnak. Add{Service}A bővítménymetelyek gyakoriak ASP.NET Core-ban és .NET-ben egyaránt.

✔️ VEGYE FIGYELEMBE azokat a neveket, amelyek a szolgáltatást más ajánlatokból egyértelműsíti.

❌ NE használjon olyan neveket, amelyek már részei a hivatalos Microsoft-csomagok .NET-ökoszisztémájának.

✔️ FONTOLJA meg a bővítménymetelyeket elérhetővé tevő statikus osztályok elnevezését, mivel {Type}Extensionsaz {Type} a típus, amelyet kiterjeszt.

Útmutató a névtérhez

A Microsoft-csomagok a Microsoft.Extensions.DependencyInjection névteret használják a különböző szolgáltatásajánlatok regisztrációjának egységesítésére.

✔️ FONTOLJA meg egy olyan névteret, amely egyértelműen azonosítja a csomagajánlatot.

❌ NE használja a névteret nem Microsoft.Extensions.DependencyInjection hivatalos Microsoft-csomagokhoz.

Paraméter nélküli

Ha a szolgáltatás minimális vagy nem explicit konfigurációval működik, fontolja meg a paraméter nélküli bővítménymetódus használatát.

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

Az előző kódban a AddMyLibraryServicekövetkező:

IConfiguration Paraméter

Ha olyan kódtárat hoz létre, amely számos lehetőséget tesz elérhetővé a felhasználók számára, érdemes lehet megfontolni egy paraméterkiterjesztési IConfiguration módszer megkövetelését. A várt IConfiguration példányt a függvény használatával IConfiguration.GetSection a konfiguráció egy elnevezett szakaszára kell hatókörbe helyezni.

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

Az előző kódban a AddMyLibraryServicekövetkező:

Az ebben a mintában szereplő fogyasztók a nevesített IConfiguration szakasz hatókörrel ellátott példányát adják meg:

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 hívás .AddMyLibraryService a típuson IServiceCollection történik.

A kódtár szerzőjeként az alapértelmezett értékek megadása Önön múlik.

Feljegyzés

A konfigurációt egy beállításpéldányhoz lehet kötni. Azonban fennáll a névütközések kockázata , ami hibákat fog okozni. Emellett ha így manuálisan köti meg a kötést, a beállítási minta használatát az egyszer olvashatóra korlátozhatja. A beállítások módosításai nem lesznek újrakötve, mivel az ilyen felhasználók nem fogják tudni használni az IOptionsMonitor felületet.

services.AddOptions<LibraryOptions>()
    .Configure<IConfiguration>(
        (options, configuration) =>
            configuration.GetSection("LibraryOptions").Bind(options));

Ehelyett a bővítménymetódust BindConfiguration kell használnia. Ez a bővítménymetódus a konfigurációt a beállításpéldányhoz köti, és egy változási jogkivonat forrását is regisztrálja a konfigurációs szakaszhoz. Ez lehetővé teszi a felhasználók számára az IOptionsMonitor felület használatát.

Konfigurációs szakasz elérési útja paraméter

Előfordulhat, hogy a tár felhasználói meg szeretnék adni a konfigurációs szakasz elérési útját a mögöttes TOptions típus kötéséhez. Ebben a forgatókönyvben egy paramétert string határoz meg a bővítménymetódusban.

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

Az előző kódban a AddMyLibraryServicekövetkező:

A következő példában a Microsoft.Extensions.Options.DataAnnotations NuGet-csomag az adatjegyzetek érvényesítésének engedélyezésére szolgál. Az SupportOptions osztály a következőképpen van definiálva:

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

Tegyük fel, hogy a következő JSON-appsettings.json fájlt használja:

{
    "Support": {
        "Url": "https://support.example.com",
        "Email": "help@support.example.com",
        "PhoneNumber": "+1(888)-SUPPORT"
    }
}

Action<TOptions> Paraméter

Előfordulhat, hogy a könyvtár felhasználói olyan lambdakifejezést szeretnének nyújtani, amely a beállításosztály egy példányát adja meg. Ebben a forgatókönyvben egy paramétert Action<LibraryOptions> határoz meg a bővítménymetódusban.

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

Az előző kódban a AddMyLibraryServicekövetkező:

  • Kiterjeszti a példányt IServiceCollection
  • Olyan paramétert Action<T>configureOptions határoz meg, amelyben T a LibraryOptions
  • A művelet által configureOptions adott hívások Configure

Az ebben a mintában szereplő felhasználók lambda kifejezést (vagy a paraméternek megfelelő Action<LibraryOptions> meghatalmazottat) adnak meg:

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

Beállítások példányparamétere

Előfordulhat, hogy a kódtár felhasználói inkább beágyazott beállításpéldányt biztosítanak. Ebben a forgatókönyvben egy olyan bővítménymetódust tesz elérhetővé, amely a beállításobjektum egy példányát használja. LibraryOptions

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

Az előző kódban a AddMyLibraryServicekövetkező:

Az ebben a mintában szereplő fogyasztók az osztály egy példányát adják meg, amely beágyazottan határozza meg a LibraryOptions kívánt tulajdonságértékeket:

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

Konfiguráció utáni

Miután az összes konfigurációs beállításérték meg van kötve vagy meg van adva, elérhető a konfiguráció utáni funkció. Ha ugyanazt Action<TOptions> a korábban részletezett paramétert adja meg, akkor dönthet úgy, hogy meghívja PostConfigure. A konfigurálás utáni futtatás az összes .Configure hívás után. Néhány oka van annak, hogy érdemes megfontolni a következő használatát PostConfigure:

  • Végrehajtási sorrend: Felülbírálhatja a .Configure hívásokban beállított konfigurációs értékeket.
  • Ellenőrzés: Az összes többi konfiguráció alkalmazása után ellenőrizheti, hogy az alapértelmezett értékek be lettek-e állítva.
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;
    }
}

Az előző kódban a AddMyLibraryServicekövetkező:

Az ebben a mintában szereplő felhasználók egy lambda kifejezést (vagy egy olyan meghatalmazottat) biztosítanak, amely megfelel a Action<LibraryOptions> paraméternek, ugyanúgy, mint egy Action<TOptions> nem utólagos konfigurációs forgatókönyvben:

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

Lásd még