ASP.NET Core的配置(3): 将配置绑定为对象[下篇]
我们在《读取配置信息》通过实例的形式演示了如何利用Options模型以依赖注入的方式直接获取由指定配置节绑定生成的Options对象,我们再次回顾一下当初我们编写的程序。如下面的代码片段所示,基于Options模型的配置绑定的编程基本采用这样的模式:先后调用ServiceCollection的扩展方法AddOption和Configure注册Options模型相关的服务并完成Options类型与指定配置节之间的映射,然后利用由此生成ServiceProvider获得一个类型为IOptions<TOptions>的服务示例,后者的Value就是配置绑定生成的Options对象。
1: FormatSettings settings = new ServiceCollection()
2: .AddOptions()
3: .Configure<FormatSettings>(configuration)
4: .BuildServiceProvider()
5: .GetService<IOptions<FormatSettings>>()
6: .Value;
一、IOptions <TOptions>
由于Options模型的编程仅仅涉及到上述几个方法的调用,所以只要搞清楚这几个方法背后的实现逻辑,我们也就彻底了解了Options模型的实现原理。首先当我们调用ServiceCollection的扩展方法时,实际上仅仅是按照如下的方式注册了一个针对IOptions <TOptions>接口类型的服务而已。服务接口IOptions<TOptions>仅仅定义了一个只读属性Value,该属性返回的正是绑定了指定配置数据的Options对象。
1: public static class ServiceCollectionExtensions
2: {
3: public static IServiceCollection AddOptions(this IServiceCollection services)
4: {
5: return services.AddSingleton(typeof(IOptions<>), typeof(OptionsManager<>));
6: }
7: }
8:
9: public interface IOptions<TOptions> where TOptions:class, new()
10: {
11: TOptions Value { get; }
12: }
通过上面的给出的代码片段我们不难看出,AddOptions方法实际上是以Singleton模式注册了一个类型为OptionsManager<TOptions>的服务,如下所示的代码片段基本反映了该类型的实现逻辑。如下面的代码片段所示,OptionsManager<TOptions>的只读属性Value返回的Options对象是以“延迟加载(Lazy Loading)”的形式被提供。Options对象创建的逻辑也很简单,我们直接调用其默认构造函数创建一个空的Options对象,然后将其递交给在构造函数中指定的一系列IConfigureOptions<TOptions>进行设置,配置绑定就这这个过程中完成。
1: public class OptionsManager<TOptions> : IOptions<TOptions> where TOptions : class, new()
2: {
3: private Lazy<TOptions> optionsAccessor;
4: public OptionsManager(IEnumerable<IConfigureOptions<TOptions>> setups)
5: {
6: optionsAccessor = new Lazy<TOptions>(() =>
7: {
8: TOptions options = new TOptions();
9: setups.ForEach(it => it.Configure(options));
10: return options;
11: });
12: }
13: public TOptions Value
14: {
15: get { return optionsAccessor.Value; }
16: }
17: }
二、IConfigureOptions<TOptions>
IConfigureOptions<TOptions>接口抽象了针对Options对象的配置行为,这个行为体现在定义其中的Configure方法。ConfigureOptions<TOptions>实现了这个接口,它采用在构造函数提供的Action<TOptions>完成对Options对象的配置。
1: public interface IConfigureOptions<TOptions> where TOptions : class, new()
2: {
3: void Configure(TOptions options);
4: }
5:
6: public class ConfigureOptions<TOptions> : IConfigureOptions<TOptions> where TOptions : class, new()
7: {
8: public Action<TOptions> Action { get; private set; }
9: public ConfigureOptions(Action<TOptions> action)
10: {
11: this.Action = action;
12: }
13: public void Configure(TOptions options)
14: {
15: this.Action(options);
16: }
17: }
针对Options对象的配置绑定工作实现在一个名为ConfigureFromConfigurationOptions<TOptions>的类中。如下面的代码片段所示,这个类型直接继承ConfigureOptions<TOptions>,在构造函数中指定的Configuration对象承载了最终需要绑定到Options对象上的配置数据,它直接调用Configuration对象的扩展方法Bind完成了针对Options对象的配置绑定。
1: public class ConfigureFromConfigurationOptions<TOptions>: ConfigureOptions<TOptions> where TOptions : class, new()
2: {
3: public ConfigureFromConfigurationOptions(IConfiguration configuration) : base(options => configuration.Bind(options))
4: { }
5: }
在Options模型中,ConfigureFromConfigurationOptions<TOptions>对象通过扩展方法Configure方法被注册到指定的ServiceCollection对象中。如下面的代码片段所示,Configure方法直接利用作为参数传入的Configuration对象创建一个ConfigureFromConfigurationOptions<TOptions>对象,并将这个对象注册到ServiceCollection之中。
1: public static class ServiceCollectionExtensions
2: {
3: public static IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration configuration)
4: where TOptions : class, new()
5: {
6: return services.AddInstance<IConfigureOptions<TOptions>>(new ConfigureFromConfigurationOptions<TOptions>(configuration));
7: }
8: }
三、Options对象的提供
整个Options模型以两个注册到ServiceCollection的服务为核心,这两个服务对应的服务接口分别是IOptions <TOptions>和IConfigureOptions<TOptions>,前者直接提供最终绑定了配置数据的Options对象,后者则在Options对象返回之前对它实施相应的初始化工作。这个两个服务分别通过扩展方法AddOptions和Configure方法注册到指定的ServiceCollection之中,服务的真实类型分别是OptionsManager<TOptions>和ConfigureFromConfigurationOptions<TOptions>,后者派生于ConfigureOptions<TOptions>。右图所示的UML体现了Options模型中涉及的这些接口和类型之间的关系。
对于一个包含服务注册描述信息的ServiceCollection,当我们分别调用其扩展方法AddOptions和Configure完成了相应的服务注册之后,我们就可以利用由它生成的ServiceProvider对象来提供针对接口类型IOptions <TOptions>的服务实例,并通过后者的只读属性Value得到配置绑定生成的Options对象。
ServiceProvider提供的这个服务实例自然是一个OptionsManager<TOptions>对象,当ServiceProvider调用构造函数对它进行实例化的时候,我们注册的ConfigureFromConfigurationOptions<TOptions>对象会以构造器注入的形式作为参数。在构造函数执行过程中,一个空的Options对象先被创建出来后会作为参数调用ConfigureFromConfigurationOptions<TOptions>的Configure方法,后者将在预先指定的Configuration对象绑定到这个Options对象之上。
ASP.NET Core的配置(1):读取配置信息
ASP.NET Core的配置(2):配置模型详解
ASP.NET Core的配置(3): 将配置绑定为对象[上篇]
ASP.NET Core的配置(3): 将配置绑定为对象[下篇]
ASP.NET Core的配置(4):多样性的配置源[上篇]
ASP.NET Core的配置(4):多样性的配置源[中篇]
ASP.NET Core的配置(4):多样性的配置源[下篇]
ASP.NET Core的配置(5):配置的同步[上篇]
ASP.NET Core的配置(5):配置的同步[下篇]
ASP.NET Core的配置(3): 将配置绑定为对象[下篇]的更多相关文章
- asp.net core 教程(五)-配置
Asp.Net Core-配置 Asp.Net Core-配置 在这一章,我们将讨论 ASP.NET Core项目的相关的配置.在解决方案资源管理器中,您将看到 Startup.cs 文件.如果你有以 ...
- asp.net core重新加载应用配置
asp.net core重新加载应用配置 Intro 我把配置放在了数据库或者是Redis里,配置需要修改的时候我要直接修改数据库,然后调用一个接口去重新加载应用配置,于是就尝试写一个运行时重新加载配 ...
- Linux CentOS7部署ASP.NET Core应用程序,并配置Nginx反向代理服务器
前言: 本篇文章主要讲解的是如何在Linux CentOS7操作系统搭建.NET Core运行环境并发布ASP.NET Core应用程序,以及配置Nginx反向代理服务器.因为公司的项目一直都是托管在 ...
- ASP.NET Core应用程序的参数配置及使用(转载)
本文结构 提前准备 参数配置方式 appsettings.json 环境变量 命令行参数 在控制器中使用配置参数 注入IConfiguration对象 注入IOptions对象 总结 应用程序的开发不 ...
- ASP.NET Core框架深度学习(二) 管道对象
4.HttpContext 第一个对象 我们的ASP.NET Core Mini由7个核心对象构建而成.第一个就是大家非常熟悉的HttpContext对象,它可以说是ASP.NET Core应用开发中 ...
- ASP.NET Core 在 JSON 文件中配置依赖注入
前言 在上一篇文章中写了如何在MVC中配置全局路由前缀,今天给大家介绍一下如何在在 json 文件中配置依赖注入. 在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等 ...
- ASP.NET Core 注入和获取 AppSettings 配置
ASP.NET Core 项目中有个appsettings.json配置文件,用于存放一些配置信息,比如数据库连接字符串等,但访问的话,只能在 ASP.NET Core 项目中获取,如果我们在其他项目 ...
- asp.net core 2.0中的配置(1)---Configuration
配置就是一个装配数据字典的过程,一个字典也就是一个键值对,所以从配置就是键值对. 在asp.net core中关于配置是由四个基本的类型来支撑的,是①IConfigurationSource②ICon ...
- ASP.NET Core 1.0 基础之配置
来源https://docs.asp.net/en/latest/fundamentals/configuration.html ASP.NET Core 1.0支持不同的配置选项.应用配置数据可以是 ...
随机推荐
- bzoj1927最小费用最大流
其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→ =_=你TM逗我 刚要删突然感觉dinic的模 ...
- WEB应用的组成结构
- DOM常用方法总结
DOM(Document Object Model:文档对象模型)为javascript中的一部分,它为访问和修改html文档或xml文档提供了一些编程接口,DOM以对象的形式来描述文档中的内容,以树 ...
- 根据异常处理对 Java 方法的层次分类
我根据异常处理对 Java 的方法分为三个层次:1.执行层,2. 处理层,3. 调用层. 执行层方法只抛出异常 throws Exception,是作为代码的基层操作者,可能有多个层次. 处理层方法使 ...
- java分享第十八天-02( java结合testng,利用XML做数据源的数据驱动)
testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本.在这以XML为例:备注:@DataProvider的返回值类 ...
- STM32之ADC+步骤小技巧(英文)
神通广大的各位互联网的网友们.大家早上中午晚上好好好.今早起来很准时的收到了两条10086的扣月租的信息.心痛不已.怀着这心情.又开始了STM32的研究.早上做了计算机控制的PID实验,又让我想起了飞 ...
- Altium Designer之AD16在Win10系统下无法切换走线/布线模式的解决办法
有些童鞋会在Win10下使用AD16的时候发现,走线模式/布线模式(切换直角,45°,弧形等)不能切换. 问题出在输入法上,一般是切换到英文输入法即可解决,但是有一种情况是win10系统自带输入法有时 ...
- js_截取Url值
"total" -->传递参数时的名字 var reg = new RegExp("(^|&)" + "total" + &q ...
- WPF整理-使用用户选择主题的颜色和字体
“Sometimes it's useful to use one of the selected colors or fonts the user has chosen in theWindows ...
- mysql解决其他服务器不可连接问题
在安装mysql的机器上运行: 1.d:\mysql\bin\>mysql -h localhost -u root //这样应该可以进入MySQL服务器 2.mysql> ...