Vzor možností používá třídy k zajištění přístupu silného typu ke skupinám souvisejících nastavení. Pokud 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á nebo vzájemně svázaná.
Možnosti také poskytují mechanismus pro ověření konfiguračních dat. Další informace najdete v části Možnosti ověření .
Vytvoření vazby hierarchické konfigurace
Upřednostňovaným způsobem čtení souvisejících hodnot konfigurace je použití vzoru možností. Vzor možností je možný prostřednictvím IOptions<TOptions> rozhraní, kde je parametr TOptions obecného typu omezen na class. Později ho IOptions<TOptions> můžete poskytnout prostřednictvím injektáže závislostí. Další informace naleznete v tématu Injektáž závislostí v .NET.
Pokud chcete například číst zvýrazněné konfigurační hodnoty ze souboru appsettings.json :
Vytvořte následující třídu TransientFaultHandlingOptions:
public sealed class TransientFaultHandlingOptions
{
public bool Enabled { get; set; }
public TimeSpan AutoRetryDelay { get; set; }
}
Při použití vzoru možností třída options:
Nesmí být abstraktní s veřejným konstruktorem bez parametrů.
Obsahují veřejné vlastnosti pro čtení i zápis pro vazbu (pole nejsou svázaná).
Následující kód je součástí souboru Program.cs C# a:
Zavolá metodu ConfigurationBinder.Bind pro svázání třídy TransientFaultHandlingOptions s oddílem "TransientFaultHandlingOptions".
Zobrazí konfigurační data pole .
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ConsoleJson.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.Sources.Clear();
IHostEnvironment env = builder.Environment;
builder.Configuration
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
.Bind(options);
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
using IHost host = builder.Build();
// Application code should start here.
await host.RunAsync();
// <Output>
// Sample output:
V předchozím kódu má konfigurační soubor JSON svůj "TransientFaultHandlingOptions" oddíl svázaný s TransientFaultHandlingOptions instancí. To hydratuje vlastnosti objektů jazyka C# s odpovídajícími hodnotami z konfigurace.
ConfigurationBinder.Get<T> naváže a vrátí určený typ. ConfigurationBinder.Get<T> může být pohodlnější než použití ConfigurationBinder.Bind. Následující kód ukazuje, jak používat ConfigurationBinder.Get<T> s třídou TransientFaultHandlingOptions:
var options =
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
.Get<TransientFaultHandlingOptions>();
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
V předchozím kódu ConfigurationBinder.Get<T> se používá k získání instance objektu TransientFaultHandlingOptions s jeho hodnotami vlastností naplněnými z podkladové konfigurace.
Důležité
Třída ConfigurationBinder zveřejňuje několik rozhraní API, například .Bind(object instance) a .Get<T>() které nejsou omezeny na .class Při použití některého z rozhraní Options musíte dodržovat výše uvedené možnosti omezení třídy.
Alternativním přístupem při použití vzoru možností je vytvořit vazbu oddílu "TransientFaultHandlingOptions" a přidat ho do kontejneru služby injektáže závislostí. V následujícím kódu se TransientFaultHandlingOptions přidá do kontejneru služby s příkazem Configure a sváže se s konfigurací:
Parametr key je název oddílu konfigurace, který se má vyhledat. Nemusí odpovídat názvu typu, který ho představuje. Můžete mít například pojmenovaný "FaultHandling" oddíl, který může být reprezentován TransientFaultHandlingOptions třídou. V tomto případě byste funkci předali "FaultHandling"GetSection . Operátor nameof se používá jako pohodlí, když pojmenovaný oddíl odpovídá typu, který odpovídá.
Pomocí předchozího kódu přečte následující kód možnosti pozice:
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
public sealed class ExampleService(IOptions<TransientFaultHandlingOptions> options)
{
private readonly TransientFaultHandlingOptions _options = options.Value;
public void DisplayValues()
{
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={_options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={_options.AutoRetryDelay}");
}
}
V předchozím kódu se změny konfiguračního souboru JSON po spuštění aplikace nepřečtou. Pokud chcete číst změny po spuštění aplikace, použijte IOptionsSnapshot nebo IOptionsMonitor k monitorování změn, jak k nim dojde, a odpovídajícím způsobem reagovat.
Použití obecného typu obálky umožňuje oddělit životnost možnosti od kontejneru injektáže závislostí (DI). Rozhraní IOptions<TOptions>.Value poskytuje vrstvu abstrakce, včetně obecných omezení, pro váš typ možností. Přináší to následující výhody:
Vyhodnocení T instance konfigurace se odloží na přístup IOptions<TOptions>.Valuek instanci , nikoli při vkládání. To je důležité, protože můžete využívat T možnost z různých míst a zvolit sémantiku života beze změny čehokoli o T.
Při registraci možností typu Tnemusíte typ explicitně registrovat T . To je pohodlí při vytváření knihovny s jednoduchými výchozími nastaveními a nechcete vynutit volajícímu registraci možností do kontejneru DI s určitou životností.
Z pohledu rozhraní API umožňuje omezení typu T (v tomto případě T je omezena na typ odkazu).
Čtení aktualizovaných dat pomocí IOptionsSnapshot
Při použití IOptionsSnapshot<TOptions>se možnosti použijí jednou za požadavek při přístupu a po celou dobu platnosti požadavku se použijí v mezipaměti. Změny konfigurace se čtou po spuštění aplikace při použití zprostředkovatelů konfigurace, kteří podporují čtení aktualizovaných konfiguračních hodnot.
Rozdíl mezi IOptionsMonitor a IOptionsSnapshot je následující:
IOptionsMonitor je jednoúčelová služba , která načítá aktuální hodnoty možností kdykoli, což je zvlášť užitečné v jednoúčelových závislostech.
IOptionsSnapshot je vymezená služba a poskytuje snímek možností v době vytváření objektu IOptionsSnapshot<T> . Snímky možností jsou navržené pro použití s přechodnými a vymezenými závislostmi.
V předchozím kódu Configure<TOptions> se metoda používá k registraci instance konfigurace, která TOptions bude svázána s, a aktualizuje možnosti při změně konfigurace.
IOptionsMonitor
Typ IOptionsMonitor podporuje oznámení o změnách a umožňuje scénáře, ve kterých může vaše aplikace dynamicky reagovat na změny zdroje konfigurace. To je užitečné, když potřebujete reagovat na změny konfiguračních dat po spuštění aplikace. Oznámení o změnách jsou podporována pouze pro poskytovatele konfigurace založené na souborech, jako jsou například následující:
using Microsoft.Extensions.Options;
namespace ConsoleJson.Example;
public sealed class MonitorService(IOptionsMonitor<TransientFaultHandlingOptions> monitor)
{
public void DisplayValues()
{
TransientFaultHandlingOptions options = monitor.CurrentValue;
Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");
}
}
V předchozím kódu se změny konfiguračního souboru JSON po spuštění aplikace načtou.
Tip
Některé systémy souborů, jako jsou kontejnery Dockeru a sdílené síťové složky, nemusí spolehlivě odesílat oznámení o změnách. Při použití IOptionsMonitor<TOptions> rozhraní v těchto prostředích nastavte DOTNET_USE_POLLING_FILE_WATCHER proměnnou prostředí na 1 systém souborů nebo true dotazujte systém souborů na změny. Interval, ve kterém se změny dotazují, je každých čtyři sekundy a není konfigurovatelný.
Místo vytvoření dvou tříd pro vytvoření vazby Features:Personalize a Features:WeatherStationpro každou část se používá následující třída:
public class Features
{
public const string Personalize = nameof(Personalize);
public const string WeatherStation = nameof(WeatherStation);
public bool Enabled { get; set; }
public string ApiKey { get; set; }
}
Následující kód nakonfiguruje pojmenované možnosti:
public sealed class Service
{
private readonly Features _personalizeFeature;
private readonly Features _weatherStationFeature;
public Service(IOptionsSnapshot<Features> namedOptionsAccessor)
{
_personalizeFeature = namedOptionsAccessor.Get(Features.Personalize);
_weatherStationFeature = namedOptionsAccessor.Get(Features.WeatherStation);
}
}
OptionsBuilder<TOptions> slouží ke konfiguraci TOptions instancí. OptionsBuilder zjednodušuje vytváření pojmenovaných možností, protože se jedná pouze o jediný parametr počátečního AddOptions<TOptions>(string optionsName) volání místo toho, aby se zobrazoval ve všech následných voláních. Možnosti ověřování a ConfigureOptions přetížení, která přijímají závislosti služby, jsou k dispozici pouze prostřednictvím OptionsBuilder.
Při konfiguraci možností můžete použít injektáž závislostí pro přístup k registrovaným službám a použít je ke konfiguraci možností. To je užitečné, když potřebujete přístup ke službám pro konfiguraci možností. Ke službám je možné přistupovat z DI a současně konfigurovat možnosti dvěma způsoby:
Předejte delegáta konfigurace pro konfiguraci v možnostech TOptions> nástroje OptionsBuilder<.OptionsBuilder<TOptions> poskytuje přetížení konfigurace , které umožňují použití až pěti služeb ke konfiguraci možností:
Doporučuje se předat delegáta konfigurace ke konfiguraci, protože vytvoření služby je složitější. Vytvoření typu odpovídá tomu, co architektura dělá při volání Konfigurace. Volání Konfigurace registruje přechodný obecný IConfigureNamedOptions<TOptions>, který má konstruktor, který přijímá obecné typy služby zadané.
Ověřování možností
Ověření možností umožňuje ověření hodnot možností.
Následující třída vytvoří vazbu na "MyCustomSettingsSection" oddíl konfigurace a použije několik DataAnnotations pravidel:
using System.ComponentModel.DataAnnotations;
namespace ConsoleJson.Example;
public sealed class SettingsOptions
{
public const string ConfigurationSectionName = "MyCustomSettingsSection";
[Required]
[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$")]
public required string SiteTitle { get; set; }
[Required]
[Range(0, 1_000,
ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public required int Scale { get; set; }
[Required]
public required int VerbosityLevel { get; set; }
}
V předchozí SettingsOptions třídě ConfigurationSectionName obsahuje vlastnost název oddílu konfigurace, ke kterému se má vytvořit vazba. V tomto scénáři objekt options poskytuje název jeho konfiguračního oddílu.
Tip
Název oddílu konfigurace je nezávislý na objektu konfigurace, ke kterému je vázán. Jinými slovy, oddíl konfigurace pojmenovaný "FooBarOptions" může být vázán na objekt možností s názvem ZedOptions. I když může být běžné je pojmenovat stejně, není to nutné a může ve skutečnosti způsobit konflikty názvů.
Zdroj tohoto obsahu najdete na GitHubu, kde můžete také vytvářet a kontrolovat problémy a žádosti o přijetí změn. Další informace najdete v našem průvodci pro přispěvatele.
Zpětná vazba k produktu .NET
.NET je open source projekt. Vyberte odkaz pro poskytnutí zpětné vazby:
Vysvětlení a implementace injektáže závislostí v aplikaci ASP.NET Core Ke správě závislostí použijte integrovaný kontejner služby ASP.NET Core. Zaregistrujte služby v kontejneru služby.