Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Med hjälp av beroendeinmatning kan du använda alternativmönstret för att registrera dina tjänster och deras motsvarande konfigurationer. Med alternativmönstret kan användare av biblioteket (och dina tjänster) kräva instanser av alternativgränssnitt där TOptions är din alternativklass. Om du använder konfigurationsalternativ via starkt skrivna objekt kan du säkerställa konsekvent värderepresentation, aktivera validering med dataanteckningar och ta bort belastningen för att parsa strängvärden manuellt. Det finns många konfigurationsprovidrar som användarna av biblioteket kan använda. Med dessa leverantörer kan konsumenter konfigurera biblioteket på många sätt.
Som .NET-biblioteksförfattare får du allmän vägledning om hur du korrekt exponerar alternativmönstret för användare av biblioteket. Det finns olika sätt att uppnå samma sak, och flera överväganden att göra.
Namngivningskonventioner
Enligt konventionen heter Add{Service}tilläggsmetoder som ansvarar för att registrera tjänster , där {Service} är ett meningsfullt och beskrivande namn.
Add{Service} tilläggsmetoder är vanliga i både ASP.NET Core och .NET.
✔️ ÖVERVÄG namn som särskiljer din tjänst från andra erbjudanden.
❌ Använd INTE namn som redan ingår i .NET-ekosystemet från officiella Microsoft-paket.
✔️ ÖVERVÄG att namnge statiska klasser som exponerar tilläggsmetoder som {Type}Extensions, där {Type} är den typ som du utökar.
Vägledning för namnområde
Microsoft-paket använder Microsoft.Extensions.DependencyInjection namnområdet för att förena registreringen av olika tjänsterbjudanden.
✔️ ÖVERVÄG ett namnområde som tydligt beskriver ditt paketerbjudande.
❌ Använd Microsoft.Extensions.DependencyInjection INTE namnområdet för icke-officiella Microsoft-paket.
Parameterlös
Om tjänsten kan fungera med minimal eller ingen explicit konfiguration bör du överväga en metod för parameterlöst tillägg.
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;
}
}
I den föregående koden: AddMyLibraryService
- Utökar en instans av IServiceCollection
- Anropar OptionsServiceCollectionExtensions.AddOptions<TOptions>(IServiceCollection) med typparametern av
LibraryOptions - Kedjar ett anrop till Configure, som anger standardalternativvärdena
IConfiguration-parametern
När du skapar ett bibliotek som exponerar många alternativ för konsumenter kanske du vill överväga att kräva en IConfiguration metod för parametertillägg. Den förväntade IConfiguration-instansen bör begränsas till ett namngivet avsnitt i konfigurationen med hjälp av IConfiguration.GetSection-funktionen.
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;
}
}
Tips/Råd
Metoden Configure<TOptions>(IServiceCollection, IConfiguration) är en del av Microsoft.Extensions.Options.ConfigurationExtensions NuGet-paketet.
I den föregående koden: AddMyLibraryService
- Utökar en instans av IServiceCollection
- Definierar en IConfiguration parameter
namedConfigurationSection - Anropar Configure<TOptions>(IServiceCollection, IConfiguration) med den generiska typparametern på
LibraryOptionsoch instansennamedConfigurationSectionför att konfigurera
Konsumenter i det här mönstret tillhandahåller den begränsade IConfiguration instansen av det namngivna avsnittet:
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();
Anropet till .AddMyLibraryService görs på IServiceCollection typen .
Som biblioteksförfattare är det upp till dig att ange standardvärden.
Anmärkning
Det går att binda konfigurationen till en alternativinstans. Det finns dock en risk för namnkollisioner - vilket kommer att orsaka fel. När du manuellt binder på det här sättet begränsar du dessutom förbrukningen av alternativmönstret till att läsa en gång. Ändringar i inställningarna kommer inte att bindas på nytt, eftersom sådana konsumenter inte kommer att kunna använda gränssnittet IOptionsMonitor .
services.AddOptions<LibraryOptions>()
.Configure<IConfiguration>(
(options, configuration) =>
configuration.GetSection("LibraryOptions").Bind(options));
I stället bör du använda BindConfiguration tilläggsmetoden. Den här tilläggsmetoden binder konfigurationen till alternativinstansen och registrerar även en ändringstokenkälla för konfigurationsavsnittet. Detta gör att konsumenterna kan använda gränssnittet IOptionsMonitor .
Sökvägsparameter för konfigurationsavsnitt
Användare av biblioteket kanske vill ange konfigurationsavsnittets sökväg för att binda din underliggande TOptions typ. I det här scenariot definierar du en string parameter i tilläggsmetoden.
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;
}
}
I den föregående koden: AddMyLibraryService
- Utökar en instans av IServiceCollection
- Definierar en
stringparameternconfigSectionPath - Samtal:
-
AddOptions med den generiska typparametern för
SupportOptions -
BindConfiguration med den angivna
configSectionPathparametern - ValidateDataAnnotations för att aktivera validering av dataanteckning
- ValidateOnStart för att framtvinga verifiering vid start i stället för i körning
-
AddOptions med den generiska typparametern för
I nästa exempel används NuGet-paketet Microsoft.Extensions.Options.DataAnnotations för att aktivera validering av dataanteckning. Klassen SupportOptions definieras på följande sätt:
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; }
}
Anta att följande JSON -appsettings.json fil används:
{
"Support": {
"Url": "https://support.example.com",
"Email": "help@support.example.com",
"PhoneNumber": "+1(888)-SUPPORT"
}
}
Action<TOptions>-parametern
Användare av biblioteket kan vara intresserade av att tillhandahålla ett lambda-uttryck som ger en instans av din optionsklass. I det här scenariot definierar du en Action<LibraryOptions> parameter i tilläggsmetoden.
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;
}
}
I den föregående koden: AddMyLibraryService
- Utökar en instans av IServiceCollection
- Definierar en Action<T> parameter
configureOptionsdärTärLibraryOptions - Anrop Configure som har angetts för
configureOptionsåtgärden
Konsumenter inom detta mönster tillhandahåller ett lambda-uttryck (eller en delegering som uppfyller parametern Action<LibraryOptions>):
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();
Alternativinstansparameter
Användare av biblioteket kanske föredrar att ange en instans av infogade alternativ. I det här scenariot exponerar du en tilläggsmetod som tar en instans av ditt alternativobjekt, 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;
}
}
I den föregående koden: AddMyLibraryService
- Utökar en instans av IServiceCollection
- Anropar OptionsServiceCollectionExtensions.AddOptions<TOptions>(IServiceCollection) med typparametern av
LibraryOptions - Kedjar ett anrop till Configure, som anger standardalternativvärden som kan åsidosättas från den angivna
userOptionsinstansen
Konsumenter i det här mönstret tillhandahåller en instans av LibraryOptions klassen, som definierar önskade egenskapsvärden direkt:
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();
Efter konfiguration
När alla konfigurationsalternativvärden är bundna eller angivna är postkonfigurationsfunktioner tillgängliga. Om du exponerar samma Action<TOptions> parameter som beskrivs tidigare kan du välja att anropa PostConfigure. Efterkonfigurering sker efter alla .Configure anrop. Det finns några anledningar till varför du vill överväga att använda PostConfigure:
-
Körningsordning: Du kan åsidosätta alla konfigurationsvärden som har angetts i anropen
.Configure. - Validering: Du kan verifiera att standardvärdena har angetts när alla andra konfigurationer har tillämpats.
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;
}
}
I den föregående koden: AddMyLibraryService
- Utökar en instans av IServiceCollection
- Definierar en Action<T> parameter
configureOptionsdärTärLibraryOptions - Anrop PostConfigure som har angetts för
configureOptionsåtgärden
Konsumenter i det här mönstret tillhandahåller ett lambda-uttryck (eller en delegerare som uppfyller parametern Action<LibraryOptions>), precis som de skulle göra med parameternAction<TOptions> i ett icke-post-konfigurationsscenario.
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();