我们在《读取配置信息》通过实例的形式演示了如何利用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): 将配置绑定为对象[下篇]的更多相关文章

  1. asp.net core 教程(五)-配置

    Asp.Net Core-配置 Asp.Net Core-配置 在这一章,我们将讨论 ASP.NET Core项目的相关的配置.在解决方案资源管理器中,您将看到 Startup.cs 文件.如果你有以 ...

  2. asp.net core重新加载应用配置

    asp.net core重新加载应用配置 Intro 我把配置放在了数据库或者是Redis里,配置需要修改的时候我要直接修改数据库,然后调用一个接口去重新加载应用配置,于是就尝试写一个运行时重新加载配 ...

  3. Linux CentOS7部署ASP.NET Core应用程序,并配置Nginx反向代理服务器

    前言: 本篇文章主要讲解的是如何在Linux CentOS7操作系统搭建.NET Core运行环境并发布ASP.NET Core应用程序,以及配置Nginx反向代理服务器.因为公司的项目一直都是托管在 ...

  4. ASP.NET Core应用程序的参数配置及使用(转载)

    本文结构 提前准备 参数配置方式 appsettings.json 环境变量 命令行参数 在控制器中使用配置参数 注入IConfiguration对象 注入IOptions对象 总结 应用程序的开发不 ...

  5. ASP.NET Core框架深度学习(二) 管道对象

    4.HttpContext 第一个对象 我们的ASP.NET Core Mini由7个核心对象构建而成.第一个就是大家非常熟悉的HttpContext对象,它可以说是ASP.NET Core应用开发中 ...

  6. ASP.NET Core 在 JSON 文件中配置依赖注入

    前言 在上一篇文章中写了如何在MVC中配置全局路由前缀,今天给大家介绍一下如何在在 json 文件中配置依赖注入. 在以前的 ASP.NET 4+ (MVC,Web Api,Owin,SingalR等 ...

  7. ASP.NET Core 注入和获取 AppSettings 配置

    ASP.NET Core 项目中有个appsettings.json配置文件,用于存放一些配置信息,比如数据库连接字符串等,但访问的话,只能在 ASP.NET Core 项目中获取,如果我们在其他项目 ...

  8. asp.net core 2.0中的配置(1)---Configuration

    配置就是一个装配数据字典的过程,一个字典也就是一个键值对,所以从配置就是键值对. 在asp.net core中关于配置是由四个基本的类型来支撑的,是①IConfigurationSource②ICon ...

  9. ASP.NET Core 1.0 基础之配置

    来源https://docs.asp.net/en/latest/fundamentals/configuration.html ASP.NET Core 1.0支持不同的配置选项.应用配置数据可以是 ...

随机推荐

  1. dotnetcore 单元测试

    dotnetcore的单元测试目前支持的比较好的是xunit,首先通过nuget添加组件dotnet-test-xunit 和 xunit.如果有依赖注入可在构造方法中,相当于Nunit中的[Setu ...

  2. Code of Conduct

    v

  3. USER STORIES AND USE CASES - DON’T USE BOTH

    We’re in Orlando for a working session as part of the Core Team building BABOK V3 and over dinner th ...

  4. Putty部署tomcat

    webserver下是tomcatprojects放置项目源代码webapp下放置项目 1. 输入地址栏 登入进去32 192.168.1.32 端口号22 2.进入projects文件夹 cd pr ...

  5. Android 怎么退出整个应用程序?

    方法一: 我们在写android应用程序时,经常会遇到想退出当前Acitivity,或者直接退出应用程序.我之前的一般操作是按返回键,或者直接按home键直接返回,其实这两种操作都没有关闭当前应用程序 ...

  6. *HDU 1237 栈

    简单计算器 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  7. POJ1860 Currency Exchange(bellman-ford)

    链接:http://poj.org/problem?id=1860 Currency Exchange Description Several currency exchange points are ...

  8. MySQL主从复制技术的简单实现

    配置环境: 主从服务器操作系统均为 ubuntu15.10 主从服务器MySQL版本均为 MySQL5.6.31 主服务器IP:192.168.0.178 从服务器IP:192.168.0.145 主 ...

  9. 初探XSS

    1. 基础准备知识 (1) php: <?php ?>部分由服务器解析后并连带html代码一并返回给浏览器,类似jsp的操作,一般开发中都使用smarty模板将前端后端分开.所以在XSS跨 ...

  10. 排序合并连接(sort merge join)的原理

    排序合并连接(sort merge join)的原理 排序合并连接(sort merge join)的原理     排序合并连接(sort merge join)       访问次数:两张表都只会访 ...