前言

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. 朋友的一年工作经验跳槽字节跳动社招经历分享(已拿offer)

    虽然已经临近年末,但是还是萌生要看新机会的想法,主要的原因是觉得在目前的岗位上技术增长遇到的瓶颈,因此想去做一些更有挑战的工作.因为仍然准备继续在深圳工作,因此选定了三家公司,腾讯.字节跳动和 sho ...

  2. P4873 [USACO14DEC] Cow Jog_Gold 牛慢跑(乱搞?二分?)

    (话说最近写的这类题不少啊...) 化简:给定数轴上一系列点,向正方向移动,点不能撞在一起,如果碰到一起就需要放到另外一行,求要多少行才能满足所有点不相撞的条件. (被标签误解,老是想到二分答案... ...

  3. SpringBoot RESTful api

    一.REST简单介绍 REST代表Representational State Transfer,是一种URI风格,是一组架构约束条件和原则.REST风格服务调用就是解析URL请求,将请求由逻辑构建处 ...

  4. vue 前端处理监听关键字搜索

    根据组件的业务需要,有时候搜索是把关键字返回给后台,后台处理后再把数据返回给前端渲染(多次请求服务器):有时候是前端把页面的数据全部获取下来,前端处理关键字的搜索(影响页面加载) 我这个文章是介绍第二 ...

  5. [LC]111题 二叉树的最小深度 (递归)

    ①题目 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null,15 ...

  6. 在C\C++中char 、short 、int各占多少个字节

    在C\C++中char .short .int各占多少个字节 : #include <bits/stdc++.h> using namespace std; int main() { co ...

  7. Java开发者入职必备条件

    01.基础技术体系 我认为知识技能体系化是判断技术是否过关的第一步.知识体系化包含两层含义: 1. 能够知道技术知识图谱(高清版图谱扫文末二维码)的内容 比如分布式系统中常用的RPC技术,其背后就涉及 ...

  8. 【python测试开发栈】带你彻底搞明白python3编码原理

    在之前的文章中,我们介绍过编码格式的发展史:[文章传送门-todo].今天我们通过几个例子,来彻底搞清楚python3中的编码格式原理,这样你之后写python脚本时碰到编码问题,才能有章可循. 我们 ...

  9. 简单的 smartpointer

    水水地 发第一篇blog, 瘦身版的smartpointer. template <typename T> class CountedPtr { private: T* ptr; long ...

  10. 关闭zabbix 告警

    1. 到触发器配置界面开启Allow manual close. (可能需要在连接的模板处修改) 2. 永久关闭告警,即disable该触发器.