(13)ASP.NET Core 中的选项模式(Options)
1.前言
选项(Options)模式是对配置(Configuration)的功能的延伸。在12章(ASP.NET Core中的配置二)Configuration中有介绍过该功能(绑定到实体类、绑定至对象图、将数组绑定至类)而选项模式又有个选项类(TOptions),该选项类作用是指:把选项类中的属性与配置来源中的键关联起来。举个例,假设json文件有个Option1键,选项类中也有个叫Option1的属性名,经过选项配置,这样就能把json中的键的值映射到选项类属性值中。也可以理解在项目应用中,把一个json文件序列化到.net类。
2.常规选项配置
选项类必须为包含公共无参数构造函数的非抽象类。在appsettings.json文件中添加option1、option2、subsection的配置:
- {
- "option1": "value1_from_json",
- "option2": -,
- "subsection": {
- "suboption1": "subvalue1_from_json",
- "suboption2":
- },
- "Logging": {
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "AllowedHosts": "*"
- }
新建MyOptions类(Models/MyOptions.cs),以下类MyOptions具有三种属性:Option1和 Option2。设置默认值为可选,但以下示例中的类构造函数设置了Option1的默认值。Option2具有通过直接初始化属性设置的默认值:
- public class MyOptions
- {
- public MyOptions()
- {
- // Set default value.
- Option1 = "value1_from_ctor";
- }
- public string Option1 { get; set; }
- public int Option2 { get; set; } = ;
- }
而MyOptions类通过Configure添加到服务容器并绑定到配置:
- public void ConfigureServices(IServiceCollection services)
- {
- // Example #1: General configuration
- // Register the Configuration instance which MyOptions binds against.
- services.Configure<MyOptions>(Configuration);
- }
也可以使用自定义ConfigurationBuilder从设置文件加载选项配置时,确认基路径设置正确,添加到服务容器并绑定到配置:
- var configBuilder = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json", optional: true);
- var config = configBuilder.Build();
- services.Configure<MyOptions>(config);
以下页面模型通过IOptionsMonitor<TOptions>使用构造函数依赖关系注入来访问设置 (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下调用IndexModel.OnGet方法返回包含选项值的字符串:
- 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.通过委托配置简单选项
使用委托设置选项值。此示例应用程序使用新建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; } = ;
- }
向服务容器添加IConfigureOptions<TOptions>服务。它通过MyOptionsWithDelegateConfig使用委托来配置绑定:
- 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 = ;
- });
- }
以下页面模型通过IOptionsMonitor<TOptions>使用构造函数依赖关系注入来访问设置 (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下调用IndexModel.OnGet方法返回包含选项值的字符串:
- public HomeController(IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig)
- {
- _optionsAccessorWithDelegateConfig = optionsAccessorWithDelegateConfig;
- }
- private readonly IOptionsMonitor<MyOptionsWithDelegateConfig> _optionsAccessorWithDelegateConfig;
- public IActionResult Index()
- {
- IndexModel indexModel = new IndexModel(_optionsAccessorWithDelegateConfig);
- indexModel.OnGet();
- return View();
- }
每次调用Configure都会将IConfigureOptions<TOptions>服务添加到服务容器。在前面的示例中,Option1和Option2的值同时在appsettings.json中指定,但Option1和Option2的值被配置的委托替代。当启用多个配置服务时,指定的最后一个配置源优于其他源,由其设置配置值。运行应用程序时,页面模型的OnGet方法返回显示选项类值的字符串。
4.子选项配置
将选项绑定到配置时,选项类型中的每个属性都将绑定到窗体property[:sub-property:]的配置键。例如,MyOptions.Option1属性将绑定到从appsettings.json中的option1属性读取的键Option1。在以下代码中,已向服务容器添加IConfigureOptions<TOptions>服务。它将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定义为保留选项值:
- public class MySubOptions
- {
- public MySubOptions()
- {
- // Set default values.
- SubOption1 = "value1_from_ctor";
- SubOption2 = ;
- }
- public string SubOption1 { get; set; }
- public int SubOption2 { get; set; }
- }
以下页面模型通过IOptionsMonitor<TOptions>使用构造函数依赖关系注入来访问设置(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下调用IndexModel.OnGet方法返回包含选项值的字符串:
- 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.通过IOptionsSnapshot重新加载配置数据
IOptionsSnapshot针对请求生命周期访问和缓存选项时,每个请求只能计算一次选项。以下示例演示如何在更改appsettings.json(Pages/Index.cshtml.cs)后创建新的 IOptionsSnapshot<TOptions>。在更改appsettings.json文件和重新加载配置之前,针对服务器的多个请求返回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文件加载的初始option1和option2值:
- snapshot option1 = value1_from_json, snapshot option2 = -
将appsettings.json文件中的值更改为value1_from_json UPDATED和200。保存appsettings.json 文件。刷新浏览器,查看更新的选项值:
- snapshot option1 = value1_from_json UPDATED, snapshot option2 =
6.包含IConfigureNamedOptions的命名选项支持
命名选项支持允许应用程序在命名选项配置之间进行区分。命名选项通过OptionsServiceCollectionExtensions.Configure进行声明,其调用扩展方法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";
- });
- }
通过OnGet(Pages/Index.cshtml.cs)访问命名选项:
- 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下调用IndexModel.OnGet方法返回包含选项值的字符串:
- public HomeController(IOptionsSnapshot<MyOptions> namedOptionsAccessor)
- {
- _namedOptionsAccessor = namedOptionsAccessor;
- }
- private readonly IOptionsSnapshot<MyOptions> _namedOptionsAccessor;
- public IActionResult Index()
- {
- IndexModel indexModel = new IndexModel(_namedOptionsAccessor);
- indexModel.OnGet();
- return View();
- }
5.1使用ConfigureAll方法配置所有选项
使用ConfigureAll方法可以配置所有选项实例。以下代码将针对包含公共值的所有配置实例配置Option1。将以下代码手动添加到Startup.ConfigureServices方法:
- services.ConfigureAll<MyOptions>(myOptions =>
- {
- myOptions.Option1 = "ConfigureAll replacement value";
- });
在Home/Index控制器Action下调用IndexModel.OnGet方法返回包含选项值的字符串:
参考文献:
ASP.NET Core 中的选项模式
(13)ASP.NET Core 中的选项模式(Options)的更多相关文章
- asp.net core 3.0 选项模式1:使用
本篇只是从应用角度来说明asp.net core的选项模式,下一篇会从源码来分析 1.以前的方式 以前我们使用web.config/app.config时是这样使用配置的 var count = Co ...
- ASP.NET Core 学习笔记 第五篇 ASP.NET Core 中的选项
前言 还记得上一篇文章中所说的配置吗?本篇文章算是上一篇的延续吧.在 .NET Core 中读取配置文件大多数会为配置选项绑定一个POCO(Plain Old CLR Object)对象,并通过依赖注 ...
- C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入
C# 嵌入dll 在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...
- ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态
原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...
- 避免在ASP.NET Core中使用服务定位器模式
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:服务定位器(Service Locator)作为一种反模式,一般情况下应该避免使用,在 ...
- [译]ASP.NET Core中使用MediatR实现命令和中介者模式
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9866068.html 在本文中,我将解释命令模式,以及如何利用基于命令模式的第三方库来实现它们,以及如何 ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...
- Asp.Net Core中服务的生命周期选项区别和用法
在做一个小的Demo中,在一个界面上两次调用视图组件,并且在视图组件中都调用了数据库查询,结果发现,一直报错,将两个视图组件的调用分离,单独进行,却又是正常的,寻找一番,发现是配置依赖注入服务时,对于 ...
随机推荐
- Docker安装nacos1.0.0固定ip单机模式
1 从dockerHub拉取镜像到本地 docker pull nacos/nacos-server:1.0.0 2 创建目录(宿主机) 2.1 日志目录 mkdir -p /docker/nacos ...
- 用ASP.NET Core重写了一款网络考试培训的免费软件
在IT圈混迹了近十年,今已正当而立之年却仍一事无成,心中倍感惶恐惭愧.面对竟争如此激列的环境,该如何应对?却也知不能让自已闲着,得转起来,动起来.于是,便想着利用最新技术栈将自已原来的收费产品重写一次 ...
- Go - Map 集合
目录 概述 声明 Map 生成 JSON 编辑和删除 推荐阅读 概述 Map 集合是无序的 key-value 数据结构. Map 集合中的 key / value 可以是任意类型,但所有的 key ...
- 一张图带你了解webpack的require.context
很多人应该像我一样,对于webpack的require.context都是一知半解吧.网上很多关于require.context的使用案例,但是我没找到可以帮助我理解这个知识点的,于是也决定自己来探索 ...
- XML中如果有特殊字符,比如> < 解决方案
//只需要在代码前加这个就可以了<![CDATA[ 把代码写到这个位置 ]]>
- redis 发布和订阅实现
参考文献 15天玩转redis -- 第九篇 发布/订阅模式 <Redis设计与实现> 命令简介 在redis用户手册中,跟发布订阅相关的命令有如下的六个: PSUBSCRIBE PUBL ...
- django基础知识之HttpReqeust对象:
HttpReqeust对象 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象 视图函数的第一个参数是HttpRequest对象 在django.http模块中定义了HttpR ...
- VS2013日常使用若干技巧+快捷键
1.注释的方法 1)sqlserver中,单行注释:— — 多行注释:/* 代码 */ 2)C#中,单行注释:// 多行注释:/* 代码 */ 3)C#中多行注释的快捷方式:先选中你要注 ...
- 开源FTP/SFTP客户端 FileZilla v3.31.0 绿色便携版
下载地址:点我 基本介绍 FileZilla是一种快速.可信赖的FTP客户端以及服务器端开放源代码程式,具有多种特色.直觉的接口.可控性.有条理的界面和管理多站点的简化方式使得Filezilla客户端 ...
- 解决webpack打包速度慢的解决办法
技巧1 webpack在打包的时候第一次总是会做很长的准备工作,包括加载插件之类的.在刚接触webpack的时候总是webpack一下-测一下-改一下-再webpack一下,这种方式最后让很多人崩溃了 ...