前言

ASP.NET Core 后我们的配置变得更加轻量级了,在ASP.NET Core中,配置模型得到了显著的扩展和增强,应用程序配置可以存储在多环境变量配置中,appsettings.json用户机密等 并可以通过应用程序中的相同界面轻松访问,除此之外,ASP.NET中的新配置系统允许使用Options的强类型设置。

强类型Options

在ASP.NET Core中没有AppSettings["Key"]默认方法,那么推荐的是创建强类型的配置类,去绑定配置项。


public class MyOptions
{
public string Name { get; set; } public string Url { get; set; }
}

然后我们在appsettings.json中添加如下内容:


{
"MyOptions":
{
"Name": "TestName",
"Url": "TestUrl"
}
}

配置绑定到类

ConfigureServices方法进行配置以绑定到类

        public void ConfigureServices(IServiceCollection services)
{ services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));
services.AddControllers(); }

MyOptions只需将IOptions<>类的实例注入控制器中,然后通过Value属性获取Myoptions:


public class WeatherForecastController : ControllerBase
{
private readonly MyOptions _options;
public WeatherForecastController(IOptions<MyOptions> options)
{
_options = options.Value;
} [HttpGet]
public OkObjectResult Get() {
return Ok(string.Format("Name:{0},Url:{1}", _options.Name,_options.Url));
}
}

Configure

委托配置

//基础注册方式
services.Configure<MyOptions>(o => { o.Url = "MyOptions"; o.Name = "Name111"; });
//指定具体名称
services.Configure<MyOptions>("Option", o => { o.Url = "MyOptions"; o.Name = "Name111"; }) ;
//配置所有实例
services.ConfigureAll<MyOptions>(options =>{ options.Name = "Name1"; options.Url = "Url1";});
通过配置文件配置

// 使用配置文件来注册实例
services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));
// 指定具体名称
services.Configure<MyOptions>("Option", Configuration.GetSection("MyOptions"));
PostConfigure

PostConfigure会在Configure注册完之后再进行注册


services.PostConfigure<MyOptions>(o => o.Name = "Name1");
services.PostConfigure<MyOptions>("Option", o => o.Name = "Name1");
services.PostConfigureAll<MyOptions>(o => o.Name = "Name1");

源码解析

IConfigureOptions接口


public interface IConfigureOptions<in TOptions> where TOptions : class
{ void Configure(TOptions options);
}

Configure为方便使用IConfigureOptions注册单例ConfigureNamedOptions


public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions)
where TOptions : class
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
} if (configureOptions == null)
{
throw new ArgumentNullException(nameof(configureOptions));
} services.AddOptions();
services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, configureOptions));
return services;
}

上面代码IConfigureOptions实现了ConfigureNamedOptions,那我们再来看看内部源码

ConfigureNamedOptions 其实就是把我们注册的Action包装成统一的Configure方法,以方便后续创建Options实例时,进行初始化。


public class ConfigureNamedOptions<TOptions> : IConfigureNamedOptions<TOptions> where TOptions : class
{ public ConfigureNamedOptions(string name, Action<TOptions> action)
{
Name = name;
Action = action;
} public string Name { get; } public Action<TOptions> Action { get; } public virtual void Configure(string name, TOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
} // Null name is used to configure all named options.
if (Name == null || name == Name)
{
Action?.Invoke(options);
}
}
public void Configure(TOptions options) => Configure(Options.DefaultName, options);
}

services.Configure(Configuration.GetSection("MyOptions")); 我们不指定具体名称的时候默认是如下代码片段


public virtual void Configure(string name, TOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
} // Null name is used to configure all named options.
if (Name == null || name == Name)
{
Action?.Invoke(options);
}
}
public void Configure(TOptions options) => Configure(Options.DefaultName, options);

默认使用的是Options.DefaultName

AddOptions默认方法默认为我们注册了一些核心的类


public static IServiceCollection AddOptions(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
} services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>)));
services.TryAdd(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsManager<>)));
services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>)));
services.TryAdd(ServiceDescriptor.Transient(typeof(IOptionsFactory<>), typeof(OptionsFactory<>)));
services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>)));
return services;
}

ASP.NET Core 选项模式源码学习Options Configure(一)的更多相关文章

  1. ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)

    前言 IOptionsMonitor 是一种单一示例服务,可随时检索当前选项值,这在单一实例依赖项中尤其有用.IOptionsMonitor用于检索选项并管理TOption实例的选项通知, IOpti ...

  2. ASP.NET Core 选项模式源码学习Options IOptions(二)

    前言 上一篇文章介绍IOptions的注册,本章我们继续往下看 IOptions IOptions是一个接口里面只有一个Values属性,该接口通过OptionsManager实现 public in ...

  3. ASP.NET Core 2.1 源码学习之 Options[1]:Configure

    配置的本质就是字符串的键值对,但是对于面向对象语言来说,能使用强类型的配置是何等的爽哉! 目录 ASP.NET Core 配置系统 强类型的 Options Configure 方法 Configur ...

  4. ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor

    前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式.而 IOptionsMonitor 则要求配置源必须是 ...

  5. ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor 【转】

    原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-monitor-in-asp-net-core. ...

  6. ASP.NET Core 2.1 源码学习之 Options[1]:Configure 【转】

    原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-configure-in-asp-net-core.html 配置 ...

  7. ASP.NET Core 2.1 源码学习之 Options[2]:IOptions

    在 上一章 中,介绍了Options的注册,而在使用时只需要注入 IOption<T> 即可: public ValuesController(IOptions<MyOptions& ...

  8. ASP.NET Core 2.1 源码学习之 Options[2]:IOptions 【转】

    原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-in-asp-net-core.html 在 上 ...

  9. .NET Core 2.1 源码学习:看 SocketsHttpHandler 如何在异步方法中连接 Socket

    在 .NET Core 2.1 中,System.Net.Sockets 的性能有了很大的提升,最好的证明是 Kestrel 与 HttpClient 都改为使用 System.Net.Sockets ...

随机推荐

  1. AutoCad 二次开发 .net 之创建Table

    我使用了COM对象来在cad2018中创建table表格,需要的ObjectArx开发包可以在官网上下载,并且需要使用.netframework4.6的库才行. 项目里除了引用常规的Cad开发dll, ...

  2. linux下安装opencv3.0

    查版本gcc --version 需>4.8python 2.7+cmake --version numpy 以上是必须的 linux下安装opencv3.0<pre>https:/ ...

  3. jquery正确获取iframe里元素的方法

    <iframe id="_ae_frame" width="100%" height="100%" frameborder=" ...

  4. [ISE调试] 在ISE调试过程中,遇到过的error以及消除办法

    1.Incompatible IOB's are locked to the same bank 15,具体如右图, 于是去查引脚配置,发现 也就是说,在bank=15的这组IO里面,我既选了LVAM ...

  5. go中的数据结构通道-channel

    1. channel的使用 很多文章介绍channel的时候都和并发揉在一起,这里我想把它当做一种数据结构来单独介绍它的实现原理. channel,通道.golang中用于数据传递的一种数据结构.是g ...

  6. shell脚本3——调试

    bash -x file.sh 这样会把执行到的语句全部打印出来 #!/bin/bash 不会打印的程序块 set -v 需要打印的程序块 set -v 不会打印的程序块

  7. Pashmak and Graph(dp + 贪心)

    题目链接:http://codeforces.com/contest/459/problem/E 题意:给一个带权有向图, 找出其中最长上升路的长度. 题解:先按权值对所有边排序, 然后依次 u -& ...

  8. 万恶之源-python的进化

    列表 列表的增删改查 3. 列列表的嵌套 元组和元组嵌套 5. range ⼀一. 列表 1.1 列表的介绍 列表是python的基础数据类型之⼀一 ,其他编程语⾔言也有类似的数据类型. 比如JS中的 ...

  9. ssm通用 POM

    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven ...

  10. linux计算机网络基础

    OSI7层协议和TCP/IP4层网络协议 第一层:物理层,定义各种物理设备的规范,如通信距离,接口大小等. 第二层:数据链路层,基于mac地址通信是,数据报文封装和相应方式. 第三层:网络层,基于IP ...