前言

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. NOIP 模拟19

    考试状态一次不如一次,所以这次.......我经无言以对 考完试T1就A了,但不是考试时A的,所以屁用没有! 这次考试其实T1想的是正解但是自己傻逼了,感觉自己只能拿部分分,(而且我还把数据范围少看一 ...

  2. php nginx反向代理获取真实ip的教程

    php nginx反向代理获取真实ip的教程 <pre> location /getip { proxy_pass http://newmiracle.cn/ip.php; } proxy ...

  3. Unity中用Mesh画一个圆环(二)

    中目标-生成完整面 在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了. 我们把之前生成的面当作顶面,接着我们来生成底面. 还记得前面说过\(\color{#1E90FF}{D ...

  4. 在控制器中如何对frxml的控件初始化

    如果在控制器中实现Initializable这个接口,并重iInitializable这个方法 对于一个fxml文件来说它首先执行控制器的构造函数,这个时候它是无法对@FXML修饰的方法进行访问的,然 ...

  5. Geometry 判断几何是否被另一个几何/线段分割成多段

    如下图,如何判断几何多边形A被多边形B,切割为多段几何? 几何A被几何B切割 1. 获取几何A与几何B的交集C var intersectGeometry = new CombinedGeometry ...

  6. 矢量图形(Vector Picture, SVG, PDF)转TiKZ代码

    在使用LaTeX的过程中,我们需要往往需要使用一些图片,譬如,在样式文件中,但是如果在样式文件中使用外部的图片,总感觉不是那么地舒服「请原谅强迫症」.因此,想办法将图形内嵌入LaTeX文件. 首先,我 ...

  7. 一分钟带你了解下MyBatis的动态SQL!

    MyBatis的强大特性之一便是它的动态SQL,以前拼接的时候需要注意的空格.列表最后的逗号等,现在都可以不用手动处理了,MyBatis采用功能强大的基于OGNL的表达式来实现,下面主要介绍下. 一. ...

  8. PHP 修改数组中的值

    PHP 修改数组中的值 ①.二维数组可以通过 for($i = 0; $i < count(Array()); ++ $i) 这种形式修改 实例代码: // 修改 二维数组中的 name为 Ge ...

  9. 树的点分治 (poj 1741, 1655(树形dp))

    poj 1655:http://poj.org/problem?id=1655 题意: 给无根树,  找出以一节点为根,  使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子 ...

  10. ansible start canal

    - name: Start canal server shell: source /etc/profile && nohup /opt/canal/bin/startup.sh