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}Extensions
az {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 AddMyLibraryService
következő:
- Kiterjeszti a példányt IServiceCollection
- Hívások OptionsServiceCollectionExtensions.AddOptions<TOptions>(IServiceCollection) a következő típusparaméterrel:
LibraryOptions
- ConfigureHívásláncok, amelyek az alapértelmezett beállításértékeket határozzák meg
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;
}
}
Tipp.
A Configure<TOptions>(IServiceCollection, IConfiguration) metódus a Microsoft.Extensions.Options.ConfigurationExtensions
NuGet-csomag része.
Az előző kódban a AddMyLibraryService
következő:
- Kiterjeszti a példányt IServiceCollection
- Paraméter definiálása IConfiguration
namedConfigurationSection
- Az általános típusparamétert
LibraryOptions
és anamedConfigurationSection
konfigurálni kívánt példányt átadó hívások Configure<TOptions>(IServiceCollection, IConfiguration)
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 AddMyLibraryService
következő:
- Kiterjeszti a példányt IServiceCollection
- Paraméter definiálása
string
configSectionPath
- Hívások:
- AddOptions a következő általános típusparaméterrel:
SupportOptions
- BindConfiguration a megadott
configSectionPath
paraméterrel - ValidateDataAnnotations az adatjegyzet-ellenőrzés engedélyezéséhez
- ValidateOnStart az érvényesítés futásidejű helyett indításkor történő kényszerítéséhez
- AddOptions a következő általános típusparaméterrel:
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 AddMyLibraryService
következő:
- Kiterjeszti a példányt IServiceCollection
- Olyan paramétert Action<T>
configureOptions
határoz meg, amelybenT
aLibraryOptions
- 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 AddMyLibraryService
következő:
- Kiterjeszti a példányt IServiceCollection
- Hívások OptionsServiceCollectionExtensions.AddOptions<TOptions>(IServiceCollection) a következő típusparaméterrel:
LibraryOptions
- ConfigureHívásláncok, amelyek alapértelmezett beállításértékeket határoznak meg, amelyek felülírhatók az adott
userOptions
példányból
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 AddMyLibraryService
következő:
- Kiterjeszti a példányt IServiceCollection
- Olyan paramétert Action<T>
configureOptions
határoz meg, amelybenT
aLibraryOptions
- A művelet által
configureOptions
adott hívások PostConfigure
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();