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)的更多相关文章

  1. asp.net core 3.0 选项模式1:使用

    本篇只是从应用角度来说明asp.net core的选项模式,下一篇会从源码来分析 1.以前的方式 以前我们使用web.config/app.config时是这样使用配置的 var count = Co ...

  2. ASP.NET Core 学习笔记 第五篇 ASP.NET Core 中的选项

    前言 还记得上一篇文章中所说的配置吗?本篇文章算是上一篇的延续吧.在 .NET Core 中读取配置文件大多数会为配置选项绑定一个POCO(Plain Old CLR Object)对象,并通过依赖注 ...

  3. 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,这种形 ...

  4. ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态

    原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...

  5. 避免在ASP.NET Core中使用服务定位器模式

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:服务定位器(Service Locator)作为一种反模式,一般情况下应该避免使用,在 ...

  6. [译]ASP.NET Core中使用MediatR实现命令和中介者模式

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9866068.html 在本文中,我将解释命令模式,以及如何利用基于命令模式的第三方库来实现它们,以及如何 ...

  7. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  8. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

    一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...

  9. Asp.Net Core中服务的生命周期选项区别和用法

    在做一个小的Demo中,在一个界面上两次调用视图组件,并且在视图组件中都调用了数据库查询,结果发现,一直报错,将两个视图组件的调用分离,单独进行,却又是正常的,寻找一番,发现是配置依赖注入服务时,对于 ...

随机推荐

  1. Sole跟Tomcat的整合 Solr4.4 + Tomcat

    1, 下载Solr4.4 Tomcat7 2, 拷贝 solr-4.4.0\dist\solr4.4.war  => tomcat\webapps 下面 重命名为solr.war 3, 启动to ...

  2. 剖析Unreal Engine超真实人类的渲染技术Part 2 - 眼球渲染

    目录 三.眼球渲染 3.1 眼球的构造及理论 3.1.1 眼球的构造 3.1.2 眼球的渲染理论 3.2 眼球的渲染技术 3.2.1 角膜的半透和光泽反射 3.2.2 瞳孔的次表面散射 3.2.3 瞳 ...

  3. PAT L3-002: 堆栈(线段树)

    https://www.patest.cn/contests/gplt/L3-002 题意:中文题意. 思路:因为所有数<=1e5,权值线段树维护每个数出现多少次,然后每次出栈入栈都更新权值就好 ...

  4. 在FPS游戏中,玩家对音画同步感知的量化与评估

    前言 在游戏测试中,音画同步测试是个难点(所谓游戏音画同步:游戏中,音效与画面的同步程度),现在一般采用人工主观判断的方式测试,但这会带来2个问题: 无法准确量化,针对同一场景的多次测试结果可能会相反 ...

  5. 用链表和数组实现HASH表,几种碰撞冲突解决方法

    Hash算法中要解决一个碰撞冲突的办法,后文中描述了几种解决方法.下面代码中用的是链式地址法,就是用链表和数组实现HASH表. he/*hash table max size*/ #define HA ...

  6. netty实现的RPC框架

    自己手撸了一个nettyRPC框架,希望在这里给有兴趣的同学们做个参考. 要想实现nettyrpc需要了解的技术要点如下: spring的自定义注解.spring的bean的有关初始化. 反射和动态代 ...

  7. web安全测试必须注意的五个方面

    随着互联网的飞速发展,web应用在软件开发中所扮演的角色变得越来越重要,同时,web应用遭受着格外多的安全攻击,其原因在于,现在的网站以及在网站上运行的应用在某种意义上来说,它是所有公司或者组织的虚拟 ...

  8. 1.svn 彻底clear时,注意代码备份 2.借助vc助手加头文件

    1.svn 彻底clear时,注意代码备份 2.不小心彻底clear可以在回收站找到 3.借助vc助手加头文件

  9. 洛谷:P2952 [USACO09OPEN]牛线Cow Line:题解

    题目链接:https://www.luogu.org/problemnew/show/P2952 分析: 这道题非常适合练习deque双端队列,~~既然是是练习的板子题了,建议大家还是练练deque, ...

  10. WePY的脱胎换骨

    对于前端来说,尤其是开发小程序的前端来说,WePY框架一定不陌生,他是一种小程序开发框架.而且是属于类Vue风格,掌握Vue再来学习WePY学习成本极低. 今天为啥要写这篇文章呢,因为在复习WePY时 ...