Vzor možností v ASP.NET Core
Od Kirka Užkina a Ricka Andersona.
Vzor možností používá třídy k poskytnutí přístupu silného typu ke skupinám souvisejících nastavení. Když jsou nastavení konfigurace izolovaná podle scénáře do samostatných tříd, aplikace dodržuje dva důležité principy softwarového inženýrství:
- Princip oddělení rozhraní (ISP)nebo zapouzdření: Scénáře (třídy), které závisí na nastavení konfigurace, závisí pouze na nastavení konfigurace, která používají.
- Oddělení obav:Nastavení pro různé části aplikace nejsou závislé ani spolu navzájem svzájem souvisejí.
Možnosti také poskytují mechanismus pro ověření konfiguračních dat. Další informace najdete v části Ověřování možností.
Toto téma obsahuje informace o vzoru možností v ASP.NET Core. Informace o použití vzoru možností v konzolové aplikaci najdete v tématu Vzor možností v .NET.
Zobrazení nebo stažení ukázkového kódu (stažení)
Vytvoření vazby hierarchické konfigurace
Upřednostňovaným způsobem, jak číst související konfigurační hodnoty, je použít vzor možností. Například pro čtení následujících konfiguračních hodnot:
"Position": {
"Title": "Editor",
"Name": "Joe Smith"
}
Vytvořte následující PositionOptions třídu:
public class PositionOptions
{
public const string Position = "Position";
public string Title { get; set; } = String.Empty;
public string Name { get; set; } = String.Empty;
}
Třída možností:
- Musí být neabstraktní s veřejným konstruktorem bez parametrů.
- Všechny veřejné vlastnosti pro čtení i zápis typu jsou vázané.
- Pole nejsou svázána . V předchozím kódu
Positionnení svázána. TatoPositionvlastnost se používá, takže řetězec"Position"nemusí být v aplikaci pevně kódovaný při vytváření vazby třídy ke zprostředkovateli konfigurace.
Následující kód:
- Volá ConfigurationBinder. Bind pro svázání
PositionOptionstřídy sPositionoddílem. - Zobrazí
Positionkonfigurační data.
public class Test22Model : PageModel
{
private readonly IConfiguration Configuration;
public Test22Model(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult OnGet()
{
var positionOptions = new PositionOptions();
Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);
return Content($"Title: {positionOptions.Title} \n" +
$"Name: {positionOptions.Name}");
}
}
V předchozím kódu se ve výchozím nastavení změny konfiguračního souboru JSON po spuštění aplikace čtou.
ConfigurationBinder.Get<T> vytvoří vazby a vrátí zadaný typ. ConfigurationBinder.Get<T> může být pohodlnější než použití ConfigurationBinder.Bind . Následující kód ukazuje, jak použít ConfigurationBinder.Get<T> s PositionOptions třídou:
public class Test21Model : PageModel
{
private readonly IConfiguration Configuration;
public PositionOptions? positionOptions { get; private set; }
public Test21Model(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult OnGet()
{
positionOptions = Configuration.GetSection(PositionOptions.Position)
.Get<PositionOptions>();
return Content($"Title: {positionOptions.Title} \n" +
$"Name: {positionOptions.Name}");
}
}
V předchozím kódu se ve výchozím nastavení změny konfiguračního souboru JSON po spuštění aplikace čtou.
Alternativním přístupem při použití vzoru * Options _ je svázání Position oddílu a jeho přidání do kontejneru služby pro vkládání závislostí. V následujícím kódu PositionOptions je přidán do kontejneru služby s <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure_> konfigurací a vázaný na konfiguraci:
using ConfigSample.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<PositionOptions>(
builder.Configuration.GetSection(PositionOptions.Position));
var app = builder.Build();
Pomocí předchozího kódu přečte následující kód možnosti pozice:
public class Test2Model : PageModel
{
private readonly PositionOptions _options;
public Test2Model(IOptions<PositionOptions> options)
{
_options = options.Value;
}
public ContentResult OnGet()
{
return Content($"Title: {_options.Title} \n" +
$"Name: {_options.Name}");
}
}
V předchozím kódu se změny konfiguračního souboru JSON po zahájení aplikace nečtou. Pokud chcete po spuštění aplikace přečíst změny, použijte IOptionsSnapshot.
Rozhraní možností
- Nepodporuje:
- Čtení konfiguračních dat po spuštění aplikace
- Pojmenované možnosti
- Je zaregistrovaný jako Singleton a může být injektován do libovolné životnosti služby.
- Je užitečná ve scénářích, kde by se měly možnosti při každém požadavku překompilovat. Další informace najdete v tématu Použití IOptionsSnapshot ke čtení aktualizovaných dat.
- Je zaregistrovaný jako Vymezený, a proto ho nelze vloženého do služby Singleton.
- Podporuje pojmenované možnosti.
- Slouží k načtení možností a správě oznámení možností
TOptionspro instance. - Je zaregistrovaný jako Singleton a může být injektován do libovolné životnosti služby.
- Podporuje:
- Oznámení o změně
- pojmenované možnosti
- Konfigurace s možnostmi opětovného načtení
- Selektivní možnosti zneplatnění ( IOptionsMonitorCache<TOptions> )
Scénáře po konfiguraci umožňují nastavení nebo změnu možností po IConfigureOptions<TOptions> dokončení veškeré konfigurace.
IOptionsFactory<TOptions> zodpovídá za vytváření nových instancí možností. Má jednu Create metodu. Výchozí implementace přebírá všechny zaregistrované a spouští nejprve všechny konfigurace, po kterých IConfigureOptions<TOptions> IPostConfigureOptions<TOptions> následuje následná konfigurace. Rozlišuje mezi IConfigureNamedOptions<TOptions> a a volá pouze příslušné IConfigureOptions<TOptions> rozhraní.
IOptionsMonitorCache<TOptions> používá k IOptionsMonitor<TOptions> ukládání instancí do TOptions mezipaměti. Parametr IOptionsMonitorCache<TOptions> zruší platnost instancí možností v monitorování tak, aby hodnota byla překompalována ( TryRemove ). Hodnoty je možné zadat ručně pomocí TryAdd . Metoda se používá, když by se všechny pojmenované instance měly Clear znovu vytvořit na vyžádání.
Čtení aktualizovaných dat pomocí IOptionsSnapshot
Pomocí se možnosti při přístupu k žádostem počítají jednou a po celou dobu životnosti požadavku se uchová IOptionsSnapshot<TOptions> v mezipaměti. Změny konfigurace se načtou po spuštění aplikace při použití zprostředkovatelů konfigurace, kteří podporují čtení aktualizovaných hodnot konfigurace.
Rozdíl mezi IOptionsMonitor a spočívá v IOptionsSnapshot tom, že:
IOptionsMonitorje jednosečná služba, která kdykoli načítá aktuální hodnoty možností, což je zvlášť užitečné u jednotlivých závislostí.IOptionsSnapshotje vymezená služba a poskytuje snímek možností v době, kdyIOptionsSnapshot<T>je objekt vytvořen. Snímky možností jsou navržené pro použití s přechodnými a vymezených závislostmi.
Následující kód používá IOptionsSnapshot<TOptions> .
public class TestSnapModel : PageModel
{
private readonly MyOptions _snapshotOptions;
public TestSnapModel(IOptionsSnapshot<MyOptions> snapshotOptionsAccessor)
{
_snapshotOptions = snapshotOptionsAccessor.Value;
}
public ContentResult OnGet()
{
return Content($"Option1: {_snapshotOptions.Option1} \n" +
$"Option2: {_snapshotOptions.Option2}");
}
}
Následující kód zaregistruje instanci konfigurace, která MyOptions vytvoří vazbu proti:
using SampleApp.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<MyOptions>(
builder.Configuration.GetSection("MyOptions"));
var app = builder.Build();
V předchozím kódu se načtou změny konfiguračního souboru JSON po spuštění aplikace.
IOptionsMonitor
Následující kód zaregistruje instanci konfigurace, která MyOptions se váže na .
using SampleApp.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<MyOptions>(
builder.Configuration.GetSection("MyOptions"));
var app = builder.Build();
Následující příklad používá IOptionsMonitor<TOptions> :
public class TestMonitorModel : PageModel
{
private readonly IOptionsMonitor<MyOptions> _optionsDelegate;
public TestMonitorModel(IOptionsMonitor<MyOptions> optionsDelegate )
{
_optionsDelegate = optionsDelegate;
}
public ContentResult OnGet()
{
return Content($"Option1: {_optionsDelegate.CurrentValue.Option1} \n" +
$"Option2: {_optionsDelegate.CurrentValue.Option2}");
}
}
Ve výchozím nastavení se v předchozím kódu po spuštění aplikace načtou změny konfiguračního souboru JSON.
Podpora pojmenovaných možností pomocí IConfigureNamedOptions
Pojmenované možnosti:
- Jsou užitečné, pokud se ke stejným vlastnostem váže více konfiguračních oddílů.
- Rozlišují se malá a velká písmena.
Vezměte v úvahu následující appsettings.json soubor:
{
"TopItem": {
"Month": {
"Name": "Green Widget",
"Model": "GW46"
},
"Year": {
"Name": "Orange Gadget",
"Model": "OG35"
}
}
}
Místo vytvoření dvou tříd pro vazbu a se pro každý oddíl TopItem:Month TopItem:Year používá následující třída:
public class TopItemSettings
{
public const string Month = "Month";
public const string Year = "Year";
public string Name { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
}
Následující kód nakonfiguruje pojmenované možnosti:
using SampleApp.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<TopItemSettings>(TopItemSettings.Month,
builder.Configuration.GetSection("TopItem:Month"));
builder.Services.Configure<TopItemSettings>(TopItemSettings.Year,
builder.Configuration.GetSection("TopItem:Year"));
var app = builder.Build();
Následující kód zobrazí pojmenované možnosti:
public class TestNOModel : PageModel
{
private readonly TopItemSettings _monthTopItem;
private readonly TopItemSettings _yearTopItem;
public TestNOModel(IOptionsSnapshot<TopItemSettings> namedOptionsAccessor)
{
_monthTopItem = namedOptionsAccessor.Get(TopItemSettings.Month);
_yearTopItem = namedOptionsAccessor.Get(TopItemSettings.Year);
}
public ContentResult OnGet()
{
return Content($"Month:Name {_monthTopItem.Name} \n" +
$"Month:Model {_monthTopItem.Model} \n\n" +
$"Year:Name {_yearTopItem.Name} \n" +
$"Year:Model {_yearTopItem.Model} \n" );
}
}
Všechny možnosti jsou pojmenované instance. IConfigureOptions<TOptions> Instance jsou považovány za cílené Options.DefaultName na instanci, což je string.Empty . IConfigureNamedOptions<TOptions> implementuje také IConfigureOptions<TOptions> . Výchozí implementace má IOptionsFactory<TOptions> logiku pro správné použití každé z nich. Pojmenovaná null možnost se používá k cílení na všechny pojmenované instance místo konkrétní pojmenované instance. ConfigureAllPostConfigureAlla použijte tuto konvenci.
OptionsBuilder API
OptionsBuilder<TOptions> se používá ke TOptions konfiguraci instancí. OptionsBuilder zjednodušuje vytváření pojmenovaných možností, protože se jedná pouze o jeden parametr počátečního volání namísto zobrazení ve všech následných AddOptions<TOptions>(string optionsName) voláních. Ověření možností a ConfigureOptions přetížení, která přijímají závislosti služby, jsou k dispozici pouze prostřednictvím OptionsBuilder .
OptionsBuilder se používá v části Ověřování možností.
Informace o přidání vlastního úložiště najdete v tématu Konfigurace vlastního úložiště pomocí možnosti PřidatMožnosti.
Konfigurace možností pomocí služeb pro dika
Ke službám je možné přistupovat prostřednictvím injektáže závislostí při konfiguraci možností dvěma způsoby:
Předejte delegáta konfigurace do konfigurace v OptionsBuilder <TOptions> .
OptionsBuilder<TOptions>poskytuje přetížení konfigurace, které umožňuje ke konfiguraci možností používat až pět služeb:builder.Services.AddOptions<MyOptions>("optionalName") .Configure<Service1, Service2, Service3, Service4, Service5>( (o, s, s2, s3, s4, s5) => o.Property = DoSomethingWith(s, s2, s3, s4, s5));Vytvořte typ, který implementuje IConfigureOptions<TOptions> nebo IConfigureNamedOptions<TOptions> a zaregistruje typ jako službu.
Doporučujeme předáte delegáta konfigurace ke konfiguraci, protože vytvoření služby je složitější. Vytvoření typu je ekvivalentem toho, co rozhraní dělá při volání funkce Configure. Volání funkce Configure zaregistruje přechodný obecný objekt , který má IConfigureNamedOptions<TOptions> konstruktor, který přijímá zadané obecné typy služeb.
Ověřování možností
Ověřování možností umožňuje ověřovat hodnoty možností.
Vezměte v úvahu následující appsettings.json soubor:
{
"MyConfig": {
"Key1": "My Key One",
"Key2": 10,
"Key3": 32
}
}
Následující třída se používá k vytvoření vazby k "MyConfig" oddílu konfigurace a používá několik DataAnnotations pravidel:
public class MyConfigOptions
{
public const string MyConfig = "MyConfig";
[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$")]
public string Key1 { get; set; }
[Range(0, 1000,
ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public int Key2 { get; set; }
public int Key3 { get; set; }
}
Následující kód:
- Volání AddOptions pro získání OptionsBuilder, <TOptions> který se váže na
MyConfigOptionstřídu. - Volání ValidateDataAnnotations pro povolení ověřování pomocí
DataAnnotations.
using OptionsValidationSample.Configuration;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddOptions<MyConfigOptions>()
.Bind(builder.Configuration.GetSection(MyConfigOptions.MyConfig))
.ValidateDataAnnotations();
var app = builder.Build();
Metoda ValidateDataAnnotations rozšíření je definována v balíčku Microsoft.Extensions.Options.DataAnnotations NuGet. U webových aplikací, které používají sadu SDK, se na tento balíček odkazuje Microsoft.NET.Sdk.Web implicitně ze sdílené architektury.
Následující kód zobrazí hodnoty konfigurace nebo chyby ověřování:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IOptions<MyConfigOptions> _config;
public HomeController(IOptions<MyConfigOptions> config,
ILogger<HomeController> logger)
{
_config = config;
_logger = logger;
try
{
var configValue = _config.Value;
}
catch (OptionsValidationException ex)
{
foreach (var failure in ex.Failures)
{
_logger.LogError(failure);
}
}
}
public ContentResult Index()
{
string msg;
try
{
msg = $"Key1: {_config.Value.Key1} \n" +
$"Key2: {_config.Value.Key2} \n" +
$"Key3: {_config.Value.Key3}";
}
catch (OptionsValidationException optValEx)
{
return Content(optValEx.Message);
}
return Content(msg);
}
Následující kód použije složitější ověřovací pravidlo pomocí delegáta:
using OptionsValidationSample.Configuration;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddOptions<MyConfigOptions>()
.Bind(builder.Configuration.GetSection(MyConfigOptions.MyConfig))
.ValidateDataAnnotations()
.Validate(config =>
{
if (config.Key2 != 0)
{
return config.Key3 > config.Key2;
}
return true;
}, "Key3 must be > than Key2."); // Failure message.
var app = builder.Build();
IValidateOptions pro komplexní ověřování
Následující třída implementuje IValidateOptions<TOptions> :
public class MyConfigValidation : IValidateOptions<MyConfigOptions>
{
public MyConfigOptions _config { get; private set; }
public MyConfigValidation(IConfiguration config)
{
_config = config.GetSection(MyConfigOptions.MyConfig)
.Get<MyConfigOptions>();
}
public ValidateOptionsResult Validate(string name, MyConfigOptions options)
{
string? vor = null;
var rx = new Regex(@"^[a-zA-Z''-'\s]{1,40}$");
var match = rx.Match(options.Key1!);
if (string.IsNullOrEmpty(match.Value))
{
vor = $"{options.Key1} doesn't match RegEx \n";
}
if ( options.Key2 < 0 || options.Key2 > 1000)
{
vor = $"{options.Key2} doesn't match Range 0 - 1000 \n";
}
if (_config.Key2 != default)
{
if(_config.Key3 <= _config.Key2)
{
vor += "Key3 must be > than Key2.";
}
}
if (vor != null)
{
return ValidateOptionsResult.Fail(vor);
}
return ValidateOptionsResult.Success;
}
}
IValidateOptions umožňuje přesunutí ověřovacího kódu z StartUp třídy a do třídy .
Pomocí předchozího kódu je v souboru Program.cs povoleno ověřování s následujícím kódem:
using Microsoft.Extensions.Options;
using OptionsValidationSample.Configuration;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.Configure<MyConfigOptions>(builder.Configuration.GetSection(
MyConfigOptions.MyConfig));
builder.Services.AddSingleton<IValidateOptions
<MyConfigOptions>, MyConfigValidation>();
var app = builder.Build();
Možnosti po konfiguraci
Nastavte po konfiguraci pomocí IPostConfigureOptions<TOptions> . Po konfiguraci se spustí po IConfigureOptions<TOptions> dokončení veškeré konfigurace:
using OptionsValidationSample.Configuration;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddOptions<MyConfigOptions>()
.Bind(builder.Configuration.GetSection(MyConfigOptions.MyConfig));
builder.Services.PostConfigure<MyConfigOptions>(myOptions =>
{
myOptions.Key1 = "post_configured_key1_value";
});
PostConfigure je k dispozici pro pojmenované možnosti po konfiguraci:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<TopItemSettings>(TopItemSettings.Month,
builder.Configuration.GetSection("TopItem:Month"));
builder.Services.Configure<TopItemSettings>(TopItemSettings.Year,
builder.Configuration.GetSection("TopItem:Year"));
builder.Services.PostConfigure<TopItemSettings>("Month", myOptions =>
{
myOptions.Name = "post_configured_name_value";
myOptions.Model = "post_configured_model_value";
});
var app = builder.Build();
Pomocí PostConfigureAll můžete po konfiguraci všech instancí konfigurace:
using OptionsValidationSample.Configuration;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddOptions<MyConfigOptions>()
.Bind(builder.Configuration.GetSection(MyConfigOptions.MyConfig));
builder.Services.PostConfigureAll<MyConfigOptions>(myOptions =>
{
myOptions.Key1 = "post_configured_key1_value";
});
Od Kirka Užkina a Ricka Andersona.
Vzor možností používá třídy k poskytnutí přístupu silného typu ke skupinám souvisejících nastavení. Když jsou nastavení konfigurace izolovaná podle scénáře do samostatných tříd, aplikace dodržuje dva důležité principy softwarového inženýrství:
- Princip oddělení rozhraní (ISP)nebo zapouzdření: Scénáře (třídy), které závisí na nastavení konfigurace, závisí pouze na nastavení konfigurace, která používají.
- Oddělení obav:Nastavení pro různé části aplikace nejsou závislé ani spolu navzájem svzájem souvisejí.
Možnosti také poskytují mechanismus pro ověření konfiguračních dat. Další informace najdete v části Ověřování možností.
Toto téma obsahuje informace o vzoru možností v ASP.NET Core. Informace o použití vzoru možností v konzolové aplikaci najdete v tématu Vzor možností v .NET.
Zobrazení nebo stažení ukázkového kódu (stažení)
Vytvoření vazby hierarchické konfigurace
Preferovaným způsobem čtení souvisejících hodnot konfigurace je použití vzoru možností. Pokud například chcete načíst následující konfigurační hodnoty:
"Position": {
"Title": "Editor",
"Name": "Joe Smith"
}
Vytvořte následující PositionOptions třídu:
public class PositionOptions
{
public const string Position = "Position";
public string Title { get; set; }
public string Name { get; set; }
}
Třída options:
- Musí být ne abstrakt s veřejným konstruktorem bez parametrů.
- Všechny veřejné vlastnosti typu pro čtení i zápis jsou svázány.
- Pole nejsou svázaná. V předchozím kódu není
Positionvázaný. Vlastnost se používá, takže při vytváření vazby třídy ke zprostředkovateli konfigurace nemusí být řetězec v aplikaciPosition"Position"pevný.
Následující kód:
- Zavolá ConfigurationBinder.Bind pro
PositionOptionsvazbu třídy kPositionoddílu. - Zobrazí
Positionkonfigurační data.
public class Test22Model : PageModel
{
private readonly IConfiguration Configuration;
public Test22Model(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult OnGet()
{
var positionOptions = new PositionOptions();
Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);
return Content($"Title: {positionOptions.Title} \n" +
$"Name: {positionOptions.Name}");
}
}
Ve výchozím nastavení se v předchozím kódu po spuštění aplikace čtou změny konfiguračního souboru JSON.
ConfigurationBinder.Get<T> vytvoří vazbu a vrátí zadaný typ. ConfigurationBinder.Get<T> může být pohodlnější než použití ConfigurationBinder.Bind . Následující kód ukazuje, jak použít ConfigurationBinder.Get<T> s PositionOptions třídou :
public class Test21Model : PageModel
{
private readonly IConfiguration Configuration;
public PositionOptions positionOptions { get; private set; }
public Test21Model(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult OnGet()
{
positionOptions = Configuration.GetSection(PositionOptions.Position)
.Get<PositionOptions>();
return Content($"Title: {positionOptions.Title} \n" +
$"Name: {positionOptions.Name}");
}
}
Ve výchozím nastavení se v předchozím kódu po spuštění aplikace čtou změny konfiguračního souboru JSON.
Alternativním přístupem při použití vzoru *možností _ je vytvořit vazbu oddílu a přidat ho do kontejneru služby Position injektáže závislostí. V následujícím kódu se do kontejneru služby přidá a PositionOptions <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure_> sváže s konfigurací :
public void ConfigureServices(IServiceCollection services)
{
services.Configure<PositionOptions>(Configuration.GetSection(
PositionOptions.Position));
services.AddRazorPages();
}
Pomocí předchozího kódu přečte následující kód možnosti pozice:
public class Test2Model : PageModel
{
private readonly PositionOptions _options;
public Test2Model(IOptions<PositionOptions> options)
{
_options = options.Value;
}
public ContentResult OnGet()
{
return Content($"Title: {_options.Title} \n" +
$"Name: {_options.Name}");
}
}
V předchozím kódu se změny konfiguračního souboru JSON po spuštění aplikace nečtou. Pokud chcete číst změny po spuštění aplikace, použijte IOptionsSnapshot.
Rozhraní možností
- Nepodporuje:
- Čtení konfiguračních dat po spuštění aplikace
- Pojmenované možnosti
- Je zaregistrovaný jako Singleton a může být injektován do libovolné životnosti služby.
- Je užitečná ve scénářích, kde by se měly možnosti při každém požadavku překompilovat. Další informace najdete v tématu Použití IOptionsSnapshot ke čtení aktualizovaných dat.
- Je zaregistrovaný jako Vymezený, a proto ho nelze vloženého do služby Singleton.
- Podporuje pojmenované možnosti.
- Slouží k načtení možností a správě oznámení možností
TOptionspro instance. - Je zaregistrovaný jako Singleton a může být injektován do libovolné životnosti služby.
- Podporuje:
- Oznámení o změně
- Pojmenované možnosti
- Konfigurace s možnostmi opětovného načtení
- Selektivní možnosti zneplatnění ( IOptionsMonitorCache<TOptions> )
Scénáře po konfiguraci umožňují nastavení nebo změnu možností po IConfigureOptions<TOptions> dokončení veškeré konfigurace.
IOptionsFactory<TOptions> zodpovídá za vytváření nových instancí možností. Má jednu Create metodu. Výchozí implementace přebírá všechny zaregistrované a spouští nejprve všechny konfigurace, po kterých IConfigureOptions<TOptions> IPostConfigureOptions<TOptions> následuje následná konfigurace. Rozlišuje mezi IConfigureNamedOptions<TOptions> a a volá pouze příslušné IConfigureOptions<TOptions> rozhraní.
IOptionsMonitorCache<TOptions> používá k IOptionsMonitor<TOptions> ukládání instancí do TOptions mezipaměti. Parametr IOptionsMonitorCache<TOptions> zruší platnost instancí možností v monitorování tak, aby hodnota byla překompalována ( TryRemove ). Hodnoty je možné zadat ručně pomocí TryAdd . Metoda se používá, když by se všechny pojmenované instance měly Clear znovu vytvořit na vyžádání.
Čtení aktualizovaných dat pomocí IOptionsSnapshot
Pomocí se možnosti při přístupu k žádostem počítají jednou a po celou dobu životnosti požadavku se uchová IOptionsSnapshot<TOptions> v mezipaměti. Změny konfigurace se načtou po spuštění aplikace při použití zprostředkovatelů konfigurace, kteří podporují čtení aktualizovaných hodnot konfigurace.
Rozdíl mezi IOptionsMonitor a spočívá v IOptionsSnapshot tom, že:
IOptionsMonitorje jednosečná služba, která kdykoli načítá aktuální hodnoty možností, což je zvlášť užitečné u jednotlivých závislostí.IOptionsSnapshotje vymezená služba a poskytuje snímek možností v době, kdyIOptionsSnapshot<T>je objekt vytvořen. Snímky možností jsou navržené pro použití s přechodnými a vymezených závislostmi.
Následující kód používá IOptionsSnapshot<TOptions> .
public class TestSnapModel : PageModel
{
private readonly MyOptions _snapshotOptions;
public TestSnapModel(IOptionsSnapshot<MyOptions> snapshotOptionsAccessor)
{
_snapshotOptions = snapshotOptionsAccessor.Value;
}
public ContentResult OnGet()
{
return Content($"Option1: {_snapshotOptions.Option1} \n" +
$"Option2: {_snapshotOptions.Option2}");
}
}
Následující kód zaregistruje instanci konfigurace, která MyOptions vytvoří vazbu proti:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));
services.AddRazorPages();
}
V předchozím kódu se načtou změny konfiguračního souboru JSON po spuštění aplikace.
IOptionsMonitor
Následující kód zaregistruje instanci konfigurace, která MyOptions se váže na .
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));
services.AddRazorPages();
}
Následující příklad používá IOptionsMonitor<TOptions> :
public class TestMonitorModel : PageModel
{
private readonly IOptionsMonitor<MyOptions> _optionsDelegate;
public TestMonitorModel(IOptionsMonitor<MyOptions> optionsDelegate )
{
_optionsDelegate = optionsDelegate;
}
public ContentResult OnGet()
{
return Content($"Option1: {_optionsDelegate.CurrentValue.Option1} \n" +
$"Option2: {_optionsDelegate.CurrentValue.Option2}");
}
}
Ve výchozím nastavení se v předchozím kódu po spuštění aplikace načtou změny konfiguračního souboru JSON.
Podpora pojmenovaných možností pomocí IConfigureNamedOptions
Pojmenované možnosti:
- Jsou užitečné, pokud se ke stejným vlastnostem váže více konfiguračních oddílů.
- Rozlišují se malá a velká písmena.
Vezměte v úvahu následující appsettings.json soubor:
{
"TopItem": {
"Month": {
"Name": "Green Widget",
"Model": "GW46"
},
"Year": {
"Name": "Orange Gadget",
"Model": "OG35"
}
}
}
Místo vytvoření dvou tříd pro vazbu a se pro každý oddíl TopItem:Month TopItem:Year používá následující třída:
public class TopItemSettings
{
public const string Month = "Month";
public const string Year = "Year";
public string Name { get; set; }
public string Model { get; set; }
}
Následující kód nakonfiguruje pojmenované možnosti:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<TopItemSettings>(TopItemSettings.Month,
Configuration.GetSection("TopItem:Month"));
services.Configure<TopItemSettings>(TopItemSettings.Year,
Configuration.GetSection("TopItem:Year"));
services.AddRazorPages();
}
Následující kód zobrazí pojmenované možnosti:
public class TestNOModel : PageModel
{
private readonly TopItemSettings _monthTopItem;
private readonly TopItemSettings _yearTopItem;
public TestNOModel(IOptionsSnapshot<TopItemSettings> namedOptionsAccessor)
{
_monthTopItem = namedOptionsAccessor.Get(TopItemSettings.Month);
_yearTopItem = namedOptionsAccessor.Get(TopItemSettings.Year);
}
public ContentResult OnGet()
{
return Content($"Month:Name {_monthTopItem.Name} \n" +
$"Month:Model {_monthTopItem.Model} \n\n" +
$"Year:Name {_yearTopItem.Name} \n" +
$"Year:Model {_yearTopItem.Model} \n" );
}
}
Všechny možnosti jsou pojmenované instance. IConfigureOptions<TOptions> Instance jsou považovány za cílené Options.DefaultName na instanci, což je string.Empty . IConfigureNamedOptions<TOptions> implementuje také IConfigureOptions<TOptions> . Výchozí implementace má IOptionsFactory<TOptions> logiku pro správné použití každé z nich. Pojmenovaná null možnost se používá k cílení na všechny pojmenované instance místo konkrétní pojmenované instance. ConfigureAllPostConfigureAlla použijte tuto konvenci.
OptionsBuilder API
OptionsBuilder<TOptions> se používá ke TOptions konfiguraci instancí. OptionsBuilder zjednodušuje vytváření pojmenovaných možností, protože se jedná pouze o jeden parametr počátečního volání namísto zobrazení ve všech následných AddOptions<TOptions>(string optionsName) voláních. Ověření možností a ConfigureOptions přetížení, která přijímají závislosti služby, jsou k dispozici pouze prostřednictvím OptionsBuilder .
OptionsBuilder se používá v části Ověřování možností.
Informace o přidání vlastního úložiště najdete v tématu Konfigurace vlastního úložiště pomocí možnosti PřidatMožnosti.
Konfigurace možností pomocí služeb pro dika
Ke službám je možné přistupovat prostřednictvím injektáže závislostí při konfiguraci možností dvěma způsoby:
Předejte delegáta konfigurace do konfigurace v OptionsBuilder <TOptions> .
OptionsBuilder<TOptions>poskytuje přetížení konfigurace, které umožňuje ke konfiguraci možností používat až pět služeb:services.AddOptions<MyOptions>("optionalName") .Configure<Service1, Service2, Service3, Service4, Service5>( (o, s, s2, s3, s4, s5) => o.Property = DoSomethingWith(s, s2, s3, s4, s5));Vytvořte typ, který implementuje IConfigureOptions<TOptions> nebo IConfigureNamedOptions<TOptions> a zaregistruje typ jako službu.
Doporučujeme předáte delegáta konfigurace ke konfiguraci, protože vytvoření služby je složitější. Vytvoření typu je ekvivalentem toho, co rozhraní dělá při volání funkce Configure. Volání funkce Configure zaregistruje přechodný obecný objekt , který má IConfigureNamedOptions<TOptions> konstruktor, který přijímá zadané obecné typy služeb.
Ověřování možností
Ověřování možností umožňuje ověřovat hodnoty možností.
Vezměte v úvahu následující appsettings.json soubor:
{
"MyConfig": {
"Key1": "My Key One",
"Key2": 10,
"Key3": 32
}
}
Následující třída se váže na "MyConfig" konfigurační oddíl a používá několik DataAnnotations pravidel:
public class MyConfigOptions
{
public const string MyConfig = "MyConfig";
[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$")]
public string Key1 { get; set; }
[Range(0, 1000,
ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public int Key2 { get; set; }
public int Key3 { get; set; }
}
Následující kód:
- Volání AddOptions pro získání OptionsBuilder, <TOptions> který se váže na
MyConfigOptionstřídu. - Volání ValidateDataAnnotations pro povolení ověřování pomocí
DataAnnotations.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions<MyConfigOptions>()
.Bind(Configuration.GetSection(MyConfigOptions.MyConfig))
.ValidateDataAnnotations();
services.AddControllersWithViews();
}
Metoda ValidateDataAnnotations rozšíření je definována v balíčku Microsoft.Extensions.Options.DataAnnotations NuGet. U webových aplikací, které používají sadu SDK, se na tento balíček odkazuje Microsoft.NET.Sdk.Web implicitně ze sdílené architektury.
Následující kód zobrazí hodnoty konfigurace nebo chyby ověřování:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IOptions<MyConfigOptions> _config;
public HomeController(IOptions<MyConfigOptions> config,
ILogger<HomeController> logger)
{
_config = config;
_logger = logger;
try
{
var configValue = _config.Value;
}
catch (OptionsValidationException ex)
{
foreach (var failure in ex.Failures)
{
_logger.LogError(failure);
}
}
}
public ContentResult Index()
{
string msg;
try
{
msg = $"Key1: {_config.Value.Key1} \n" +
$"Key2: {_config.Value.Key2} \n" +
$"Key3: {_config.Value.Key3}";
}
catch (OptionsValidationException optValEx)
{
return Content(optValEx.Message);
}
return Content(msg);
}
Následující kód použije složitější ověřovací pravidlo pomocí delegáta:
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions<MyConfigOptions>()
.Bind(Configuration.GetSection(MyConfigOptions.MyConfig))
.ValidateDataAnnotations()
.Validate(config =>
{
if (config.Key2 != 0)
{
return config.Key3 > config.Key2;
}
return true;
}, "Key3 must be > than Key2."); // Failure message.
services.AddControllersWithViews();
}
IValidateOptions pro komplexní ověřování
Následující třída implementuje IValidateOptions<TOptions> :
public class MyConfigValidation : IValidateOptions<MyConfigOptions>
{
public MyConfigOptions _config { get; private set; }
public MyConfigValidation(IConfiguration config)
{
_config = config.GetSection(MyConfigOptions.MyConfig)
.Get<MyConfigOptions>();
}
public ValidateOptionsResult Validate(string name, MyConfigOptions options)
{
string vor=null;
var rx = new Regex(@"^[a-zA-Z''-'\s]{1,40}$");
var match = rx.Match(options.Key1);
if (string.IsNullOrEmpty(match.Value))
{
vor = $"{options.Key1} doesn't match RegEx \n";
}
if ( options.Key2 < 0 || options.Key2 > 1000)
{
vor = $"{options.Key2} doesn't match Range 0 - 1000 \n";
}
if (_config.Key2 != default)
{
if(_config.Key3 <= _config.Key2)
{
vor += "Key3 must be > than Key2.";
}
}
if (vor != null)
{
return ValidateOptionsResult.Fail(vor);
}
return ValidateOptionsResult.Success;
}
}
IValidateOptions umožňuje přesunutí ověřovacího kódu z StartUp třídy a do třídy .
Pomocí předchozího kódu je ověřování povoleno v souboru Startup.ConfigureServices s následujícím kódem:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyConfigOptions>(Configuration.GetSection(
MyConfigOptions.MyConfig));
services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions
<MyConfigOptions>, MyConfigValidation>());
services.AddControllersWithViews();
}
Možnosti po konfiguraci
Nastavte po konfiguraci pomocí IPostConfigureOptions<TOptions> . Po konfiguraci se spustí po IConfigureOptions<TOptions> dokončení veškeré konfigurace:
services.PostConfigure<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});
PostConfigure je k dispozici pro pojmenované možnosti po konfiguraci:
services.PostConfigure<MyOptions>("named_options_1", myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});
Pomocí PostConfigureAll můžete po konfiguraci všech instancí konfigurace:
services.PostConfigureAll<MyOptions>(myOptions =>
{
myOptions.Option1 = "post_configured_option1_value";
});
Přístup k možnostem během spuštění
IOptions<TOptions> a IOptionsMonitor<TOptions> lze použít v , protože služby jsou Startup.Configure sestaveny před Configure provedením metody.
public void Configure(IApplicationBuilder app,
IOptionsMonitor<MyOptions> optionsAccessor)
{
var option1 = optionsAccessor.CurrentValue.Option1;
}
Nepoužívejte nebo IOptions<TOptions> IOptionsMonitor<TOptions> v Startup.ConfigureServices . Kvůli objednávání registrací služeb může existovat nekonzistentní stav možností.
Options.ConfigurationExtensions – NuGet balíček
Na balíček Microsoft.Extensions.Options.ConfigurationExtensions se implicitně odkazuje v ASP.NET Core aplikacích.