ASP.NET Core中的Options選項(xiàng)模式
1.前言
選項(xiàng)(Options)模式是對(duì)配置(Configuration)的功能的延伸。在12章(ASP.NET Core中的配置二)Configuration中有介紹過(guò)該功能(綁定到實(shí)體類、綁定至對(duì)象圖、將數(shù)組綁定至類)而選項(xiàng)模式又有個(gè)選項(xiàng)類(TOptions),該選項(xiàng)類作用是指:把選項(xiàng)類中的屬性與配置來(lái)源中的鍵關(guān)聯(lián)起來(lái)。舉個(gè)例,假設(shè)json文件有個(gè)Option1鍵,選項(xiàng)類中也有個(gè)叫Option1的屬性名,經(jīng)過(guò)選項(xiàng)配置,這樣就能把json中的鍵的值映射到選項(xiàng)類屬性值中。也可以理解在項(xiàng)目應(yīng)用中,把一個(gè)json文件序列化到.net類。
2.常規(guī)選項(xiàng)配置
選項(xiàng)類必須為包含公共無(wú)參數(shù)構(gòu)造函數(shù)的非抽象類。在appsettings.json文件中添加option1、option2、subsection的配置:
{ "option1": "value1_from_json", "option2": -1, "subsection": { "suboption1": "subvalue1_from_json", "suboption2": 200 }, "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*" }
新建MyOptions類(Models/MyOptions.cs),以下類MyOptions具有三種屬性:Option1和 Option2。設(shè)置默認(rèn)值為可選,但以下示例中的類構(gòu)造函數(shù)設(shè)置了Option1的默認(rèn)值。Option2具有通過(guò)直接初始化屬性設(shè)置的默認(rèn)值:
public class MyOptions { public MyOptions() { // Set default value. Option1 = "value1_from_ctor"; } public string Option1 { get; set; } public int Option2 { get; set; } = 5; }
而MyOptions類通過(guò)Configure添加到服務(wù)容器并綁定到配置:
public void ConfigureServices(IServiceCollection services) { // Example #1: General configuration // Register the Configuration instance which MyOptions binds against. services.Configure<MyOptions>(Configuration); }
也可以使用自定義ConfigurationBuilder從設(shè)置文件加載選項(xiàng)配置時(shí),確認(rèn)基路徑設(shè)置正確,添加到服務(wù)容器并綁定到配置:
var configBuilder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true); var config = configBuilder.Build(); services.Configure<MyOptions>(config);
以下頁(yè)面模型通過(guò)IOptionsMonitor<TOptions>使用構(gòu)造函數(shù)依賴關(guān)系注入來(lái)訪問(wèn)設(shè)置 (Pages/Index.cshtml.cs):
public class IndexModel { public IndexModel(IOptionsMonitor<MyOptions> optionsAccessor) { _options = optionsAccessor.CurrentValue; } private readonly MyOptions _options; public void OnGet() { // Example #1: Simple options var option1 = _options.Option1; var option2 = _options.Option2; var simpleOptions = $"option1 = {option1}, option2 = {option2}"; } }
在Home/Index控制器Action下調(diào)用IndexModel.OnGet方法返回包含選項(xiàng)值的字符串:
public HomeController(IOptionsMonitor<MyOptions> optionsAccessor) { _optionsAccessor = optionsAccessor; } private readonly IOptionsMonitor<MyOptions> _optionsAccessor; public IActionResult Index() { IndexModel indexModel = new IndexModel(_optionsAccessor); indexModel.OnGet(); return View(); }
3.通過(guò)委托配置簡(jiǎn)單選項(xiàng)
使用委托設(shè)置選項(xiàng)值。此示例應(yīng)用程序使用新建MyOptionsWithDelegateConfig類 (Models/MyOptionsWithDelegateConfig.cs):
public class MyOptionsWithDelegateConfig { public MyOptionsWithDelegateConfig() { // Set default value. Option1 = "value1_from_ctor"; } public string Option1 { get; set; } public int Option2 { get; set; } = 5; }
向服務(wù)容器添加IConfigureOptions<TOptions>服務(wù)。它通過(guò)MyOptionsWithDelegateConfig使用委托來(lái)配置綁定:
public void ConfigureServices(IServiceCollection services) { // Example #2: Options bound and configured by a delegate services.Configure<MyOptionsWithDelegateConfig>(myOptions => { myOptions.Option1 = "value1_configured_by_delegate"; myOptions.Option2 = 500; }); }
以下頁(yè)面模型通過(guò)IOptionsMonitor<TOptions>使用構(gòu)造函數(shù)依賴關(guān)系注入來(lái)訪問(wèn)設(shè)置 (Pages/Index.cshtml.cs):
public class IndexModel { private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig; public IndexModel(IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig) { _optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue; } public void OnGet() { // Example #2: Options configured by delegate var delegate_config_option1 = _optionsWithDelegateConfig.Option1; var delegate_config_option2 = _optionsWithDelegateConfig.Option2; var simpleOptionsWithDelegateConfig = $"delegate_option1 = {delegate_config_option1}, " + $"delegate_option2 = {delegate_config_option2}"; } }
在Home/Index控制器Action下調(diào)用IndexModel.OnGet方法返回包含選項(xiàng)值的字符串:
public HomeController(IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig) { _optionsAccessorWithDelegateConfig = optionsAccessorWithDelegateConfig; } private readonly IOptionsMonitor<MyOptionsWithDelegateConfig> _optionsAccessorWithDelegateConfig; public IActionResult Index() { IndexModel indexModel = new IndexModel(_optionsAccessorWithDelegateConfig); indexModel.OnGet(); return View(); }
每次調(diào)用Configure都會(huì)將IConfigureOptions<TOptions>服務(wù)添加到服務(wù)容器。在前面的示例中,Option1和Option2的值同時(shí)在appsettings.json中指定,但Option1和Option2的值被配置的委托替代。當(dāng)啟用多個(gè)配置服務(wù)時(shí),指定的最后一個(gè)配置源優(yōu)于其他源,由其設(shè)置配置值。運(yùn)行應(yīng)用程序時(shí),頁(yè)面模型的OnGet方法返回顯示選項(xiàng)類值的字符串。
4.子選項(xiàng)配置
將選項(xiàng)綁定到配置時(shí),選項(xiàng)類型中的每個(gè)屬性都將綁定到窗體property[:sub-property:]的配置鍵。例如,MyOptions.Option1屬性將綁定到從appsettings.json中的option1屬性讀取的鍵Option1。在以下代碼中,已向服務(wù)容器添加IConfigureOptions<TOptions>服務(wù)。它將MySubOptions綁定到appsettings.json文件的subsection部分:
public void ConfigureServices(IServiceCollection services) { // Example #3: Suboptions // Bind options using a sub-section of the appsettings.json file. services.Configure<MySubOptions>(Configuration.GetSection("subsection")); }
新建MySubOptions類(Models/MySubOptions.cs)將屬性SubOption1和SubOption2定義為保留選項(xiàng)值:
public class MySubOptions { public MySubOptions() { // Set default values. SubOption1 = "value1_from_ctor"; SubOption2 = 5; } public string SubOption1 { get; set; } public int SubOption2 { get; set; } }
以下頁(yè)面模型通過(guò)IOptionsMonitor<TOptions>使用構(gòu)造函數(shù)依賴關(guān)系注入來(lái)訪問(wèn)設(shè)置(Pages/Index.cshtml.cs):
public class IndexModel { private readonly MySubOptions _subOptions; public IndexModel(IOptionsMonitor<MySubOptions> subOptionsAccessor) { _subOptions = subOptionsAccessor.CurrentValue; } public void OnGet() { // Example #3: Suboptions var subOption1 = _subOptions.SubOption1; var subOption2 = _subOptions.SubOption2; var subOptions = $"subOption1 = {subOption1}, subOption2 = {subOption2}"; } }
在Home/Index控制器Action下調(diào)用IndexModel.OnGet方法返回包含選項(xiàng)值的字符串:
public HomeController(IOptionsMonitor<MySubOptions> subOptionsAccessor) { _subOptionsAccessor = subOptionsAccessor; } private readonly IOptionsMonitor<MySubOptions> _subOptionsAccessor; public IActionResult Index() { IndexModel indexModel = new IndexModel(_subOptionsAccessor); indexModel.OnGet(); return View(); }
5.通過(guò)IOptionsSnapshot重新加載配置數(shù)據(jù)
IOptionsSnapshot針對(duì)請(qǐng)求生命周期訪問(wèn)和緩存選項(xiàng)時(shí),每個(gè)請(qǐng)求只能計(jì)算一次選項(xiàng)。以下示例演示如何在更改appsettings.json(Pages/Index.cshtml.cs)后創(chuàng)建新的 IOptionsSnapshot<TOptions>。在更改appsettings.json文件和重新加載配置之前,針對(duì)服務(wù)器的多個(gè)請(qǐng)求返回appsettings.json文件提供的配置鍵值。
public class IndexModel { private readonly MyOptions _snapshotOptions; public IndexModel(IOptionsSnapshot<MyOptions> snapshotOptionsAccessor) { _snapshotOptions = snapshotOptionsAccessor.Value; } public void OnGet() { // Example #5: Snapshot options var snapshotOption1 = _snapshotOptions.Option1; var snapshotOption2 = _snapshotOptions.Option2; var snapshotOptions = $"snapshot option1 = {snapshotOption1}, " + $"snapshot option2 = {snapshotOption2}"; } }
下面顯示從appsettings.json文件加載的初始o(jì)ption1和option2值:
snapshot option1 = value1_from_json, snapshot option2 = -1
將appsettings.json文件中的值更改為value1_from_json UPDATED和200。保存appsettings.json 文件。刷新瀏覽器,查看更新的選項(xiàng)值:
snapshot option1 = value1_from_json UPDATED, snapshot option2 = 200
6.包含IConfigureNamedOptions的命名選項(xiàng)支持
命名選項(xiàng)支持允許應(yīng)用程序在命名選項(xiàng)配置之間進(jìn)行區(qū)分。命名選項(xiàng)通過(guò)OptionsServiceCollectionExtensions.Configure進(jìn)行聲明,其調(diào)用擴(kuò)展方法ConfigureNamedOptions<TOptions>.Configure:
public void ConfigureServices(IServiceCollection services) { // Example #6: Named options (named_options_1) // Register the ConfigurationBuilder instance which MyOptions binds against. // Specify that the options loaded from configuration are named // "named_options_1". services.Configure<MyOptions>("named_options_1", Configuration); // Example #6: Named options (named_options_2) // Specify that the options loaded from the MyOptions class are named // "named_options_2". // Use a delegate to configure option values. services.Configure<MyOptions>("named_options_2", myOptions => { myOptions.Option1 = "named_options_2_value1_from_action"; }); }
通過(guò)OnGet(Pages/Index.cshtml.cs)訪問(wèn)命名選項(xiàng):
public class IndexModel { private readonly MyOptions _named_options_1; private readonly MyOptions _named_options_2; public IndexModel(IOptionsSnapshot<MyOptions> namedOptionsAccessor) { _named_options_1 = namedOptionsAccessor.Get("named_options_1"); _named_options_2 = namedOptionsAccessor.Get("named_options_2"); } public void OnGet() { // Example #6: Named options var named_options_1 = $"named_options_1: option1 = {_named_options_1.Option1}, " + $"option2 = {_named_options_1.Option2}"; var named_options_2 = $"named_options_2: option1 = {_named_options_2.Option1}, " + $"option2 = {_named_options_2.Option2}"; var namedOptions = $"{named_options_1} {named_options_2}"; } }
在Home/Index控制器Action下調(diào)用IndexModel.OnGet方法返回包含選項(xiàng)值的字符串:
public HomeController(IOptionsSnapshot<MyOptions> namedOptionsAccessor) { _namedOptionsAccessor = namedOptionsAccessor; } private readonly IOptionsSnapshot<MyOptions> _namedOptionsAccessor; public IActionResult Index() { IndexModel indexModel = new IndexModel(_namedOptionsAccessor); indexModel.OnGet(); return View(); }
使用ConfigureAll方法配置所有選項(xiàng)
使用ConfigureAll方法可以配置所有選項(xiàng)實(shí)例。以下代碼將針對(duì)包含公共值的所有配置實(shí)例配置Option1。將以下代碼手動(dòng)添加到Startup.ConfigureServices方法:
services.ConfigureAll<MyOptions>(myOptions => { myOptions.Option1 = "ConfigureAll replacement value"; });
在Home/Index控制器Action下調(diào)用IndexModel.OnGet方法返回包含選項(xiàng)值的字符串:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ASP.NET Core中的Options選項(xiàng)模式
這篇文章介紹了ASP.NET Core中的Options選項(xiàng)模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04ASP.NET實(shí)現(xiàn)word文檔在線預(yù)覽功能代碼
文檔管理系統(tǒng)需要實(shí)現(xiàn)WORD能在線預(yù)覽功能,以前覺(jué)得挺難的,經(jīng)過(guò)一番研究發(fā)現(xiàn),WORD自帶的另存為可以保存為HTMl文件。2010-07-07asp.net下SQLite(輕量級(jí)最佳數(shù)據(jù)庫(kù)) 原理分析和開(kāi)發(fā)應(yīng)用
SQLite是一個(gè)開(kāi)源的嵌入式關(guān)系數(shù)據(jù)庫(kù),它在2000年由D. Richard Hipp發(fā)布,它的減少應(yīng)用程序管理數(shù)據(jù)的開(kāi)銷(xiāo),SQLite可移植性好,很容易使用,很小,高效而且可靠2011-10-10.NET?6中System.Text.Json的七個(gè)特性
這篇文章介紹了.NET?6中System.Text.Json的七個(gè)特性,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01.Net行為型設(shè)計(jì)模式之策略模式(Stragety)
這篇文章介紹了.Net行為型設(shè)計(jì)模式之策略模式(Stragety),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05.Net?Core微服務(wù)rpc框架GRPC通信實(shí)際運(yùn)用
這篇文章介紹了.Net?Core微服務(wù)rpc框架GRPC通信實(shí)際運(yùn)用,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01ASP.NET?Core中的通用主機(jī)HostBuilder
這篇文章介紹了ASP.NET?Core中的通用主機(jī)HostBuilder,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04