ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor 【转】
原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-monitor-in-asp-net-core.html
前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式。而 IOptionsMonitor 则要求配置源必须是可监听的,用来实现 Options 实例的自动更新,并对外提供了 OnChage 事件,给我们更多的控制权。
目录
- IOptionsMonitor
- OptionsMonitor源码探索
- ConfigurationChangeTokenSource
- 示例
IOptionsMonitor
对于 IOptionsMonitor 我们接触的较少,它的定义如下:
public interface IOptionsMonitor<out TOptions> { TOptions CurrentValue { get; } TOptions Get(string name); IDisposable OnChange(Action<TOptions, string> listener); }
在AddOptions
扩展方法中,可以看到它的默认实现为 OptionsMonitor:
public static IServiceCollection AddOptions(this IServiceCollection services) { services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>))); services.TryAdd(ServiceDescriptor.Transient(typeof(IOptionsFactory<>), typeof(OptionsFactory<>))); services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>))); }
OptionsMonitor源码探索
OptionsMonitor通过IOptionsChangeTokenSource
来实现事件的监听,具体如下:
public class OptionsMonitor<TOptions> : IOptionsMonitor<TOptions> where TOptions : class, new() { private readonly IOptionsMonitorCache<TOptions> _cache; private readonly IOptionsFactory<TOptions> _factory; private readonly IEnumerable<IOptionsChangeTokenSource<TOptions>> _sources; internal event Action<TOptions, string> _onChange; public OptionsMonitor(IOptionsFactory<TOptions> factory, IEnumerable<IOptionsChangeTokenSource<TOptions>> sources, IOptionsMonitorCache<TOptions> cache) { _factory = factory; _sources = sources; _cache = cache; foreach (var source in _sources) { ChangeToken.OnChange<string>(() => source.GetChangeToken(), (name) => InvokeChanged(name), source.Name); } } public TOptions CurrentValue => Get(Options.DefaultName); public virtual TOptions Get(string name) { name = name ?? Options.DefaultName; return _cache.GetOrAdd(name, () => _factory.Create(name)); } public IDisposable OnChange(Action<TOptions, string> listener) { ... } private void InvokeChanged(string name) { ... } }
首先看构造函数中的三个参数,其中 IOptionsFactory<>
在上一章已讲过,而IOptionsChangeTokenSource
则在 第一章 中介绍过,通过IConfiguration
进行配置的 Options,会注册该类型的实现,用来实现对配置源的监听:
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config) where TOptions : class { ... services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, config)); ... }
IOptionsChangeTokenSource 的定义如下:
public interface IOptionsChangeTokenSource<out TOptions> { IChangeToken GetChangeToken(); string Name { get; } }
在OptionsMonitor
的构造函数中,通过调用其GetChangeToken
方法,获取到 ChangeToken ,在 InvokeChanged
完成 *_onChange* 事件的调用:
private void InvokeChanged(string name) { name = name ?? Options.DefaultName; _cache.TryRemove(name); var options = Get(name); if (_onChange != null) { _onChange.Invoke(options, name); } }
而对外暴露的OnChange
方法,方便我们注册自己的逻辑:
public IDisposable OnChange(Action<TOptions> listener) { var disposable = new ChangeTrackerDisposable(this, listener); _onChange += disposable.OnChange; return disposable; }
这里又使用了一个 ChangeTrackerDisposable 的包装类,用来实现事件的注销:
internal class ChangeTrackerDisposable : IDisposable { private readonly Action<TOptions> _listener; private readonly OptionsMonitor<TOptions> _monitor; public ChangeTrackerDisposable(OptionsMonitor<TOptions> monitor, Action<TOptions> listener) { _listener = listener; _monitor = monitor; } public void OnChange(TOptions options) => _listener.Invoke(options); public void Dispose() => _monitor._onChange -= OnChange; }
构造函数的最后一个参数IOptionsMonitorCache
的默认实现便是 上一章 中介绍的 OptionsCache
。
ConfigurationChangeTokenSource
IConfigurationChangeTokenSource 的默认实现类是 ConfigurationChangeTokenSource
:
public class ConfigurationChangeTokenSource<TOptions> : IOptionsChangeTokenSource<TOptions> { private IConfiguration _config; public ConfigurationChangeTokenSource(IConfiguration config) : this(Options.DefaultName, config) { } public ConfigurationChangeTokenSource(string name, IConfiguration config) { if (config == null) { throw new ArgumentNullException(nameof(config)); } _config = config; } public string Name { get; } public IChangeToken GetChangeToken() { return _config.GetReloadToken(); } }
上面用到的 ChangeToken 便是通过构造函数接受的IConfiguration
类型的参数来获取的:
public interface IConfiguration
{...IChangeToken GetReloadToken(); ... }
因此要想使用IOptionsMonitor
,通常要使用IConfiguration
来注册才可以,当然,你也可以实现自己的 ConfigurationChangeTokenSource
。
示例
下面简单演示一下IOptionsMonitor
的使用:
首先创建一个控制台程序,添加appsettings.json
:
{"Name": "bob"
}
然后修改Program.cs
如下:
public class MyOptions
{public string Name { get; set; } } class Program { private IOptionsMonitor<MyOptions> _options; public Program() { var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build(); var serviceCollection = new ServiceCollection(); serviceCollection.Configure<MyOptions>(configuration); var serviceProvider = serviceCollection.BuildServiceProvider(); _options = serviceProvider.GetRequiredService<IOptionsMonitor<MyOptions>>(); } public static void Main(string[] args) { new Program().Execute(args); } public void Execute(string[] args) { Console.WriteLine(_options.CurrentValue.Name); _options.OnChange(_ => Console.WriteLine(_.Name)); Console.ReadKey(); } }
我们手动修改配置文件,便会触发OnChange事件。
附示例代码地址:https://github.com/RainingNight/AspNetCoreSample/tree/master/src/OptionsSample 。
总结
本章介绍了 IOptionsMonitor
的实现:通过 IConfiguration 所提供的 ChangeToken
,来注册监听事件,对其 CurrentValue
进行更新。到此,ASP.NET Core 中的 Options 源码也就分析完了,其本身比较简单,并没有太多东西。更具体的可以去 Github 上看完整的源码。
转载于:https://www.cnblogs.com/fuyouchen/p/9578613.html
ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor 【转】相关推荐
- ASP.NET Core 2.1 源码学习之 Options[1]:Configure
配置的本质就是字符串的键值对,但是对于面向对象语言来说,能使用强类型的配置是何等的爽哉! 目录 ASP.NET Core 配置系统 强类型的 Options Configure 方法 Configur ...
- ASP.NET Core 2.1 源码学习之 Options[2]:IOptions 【转】
原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-in-asp-net-core.html 在 上 ...
- ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式.而 IOptionsMonitor 则要求配置源必须是 ...
- ASP.NET Core 源码学习之 Options[3]:IOptionsSnapshot
2017-06-28 更新: OptionsSnapshot 已改为 OptionsManager 变更详情 IOptionsCache 已改为 IOptionsMonitorCache 变更详情 在 ...
- ASP.NET Core 源码学习之 Options[2]:IOptions
在 上一篇 中,介绍了一下Options的注册,而使用时只需要注入 IOption 即可: public ValuesController(IOptions<MyOptions> opti ...
- ASP.NET Core 源码学习之 Options[1]:Configure
ASP.NET Core 配置系统 在ASP.NET 4.X中,通常将配置存储在 web.config 中,使用静态帮助类来获取这些配置,而对 web.cofng 中进行任何修改时,则会导致应用程序池 ...
- ASP.NET Core 源码学习之 Logging[2]:Configure
在上一章中,我们对 ASP.NET Logging 系统做了一个整体的介绍,而在本章中则开始从最基本的配置开始,逐步深入到源码当中去. 默认配置 在 ASP.NET Core 2.0 中,对默认配置做 ...
- ASP.NET Core 源码学习之Logging[1]:Introduction
在ASP.NET 4.X中,我们通常使用 log4net, NLog 等来记录日志,但是当我们引用的一些第三方类库使用不同的日志框架时,就比较混乱了.而在 ASP.Net Core 中内置了日志系统, ...
- ASP.NET Core MVC 源码学习:Routing 路由
前言 最近打算抽时间看一下 ASP.NET Core MVC 的源码,特此把自己学习到的内容记录下来,也算是做个笔记吧. 路由作为 MVC 的基本部分,所以在学习 MVC 的其他源码之前还是先学习一下 ...
最新文章
- 树莓派4与英伟达Jetson Nano性能大比拼,谁是最佳的嵌入式“电脑”?
- C语言中的关键字概览
- pyQt4 for mac OS 10.8
- was not declared in this scope
- 洪磊父亲避谈洪磊获释 拘留已过24小时留滞期
- Android TextView跑马灯效果与设置文字阴影
- Django:ORM基本操作-CRUD,管理器对象objects,----->新增
- php中new与构造函数,php - 在构造函数中使用“ new”关键字 - SO中文参考 - www.soinside.com...
- mysql 解决慢sql_MySQL被慢sql hang住了,用shell脚本快速清除不断增长的慢sql的办法...
- Rust : 红楼梦一书中文字符的统计
- 手机客户端接口开发文档模板整理
- pe擦除服务器硬盘,老毛桃winpe分区助手删除分区后如何用Gutmann算法擦除硬盘数据?...
- 禅道和JIRA大对比
- 浩辰云建筑2021功能详细介绍
- Java 实现扫雷与高胜率低耗时自动扫雷 AI (下)
- 完整的境外、港澳台、电信、移动、联通、教育网、国内其他ISP的IPv4列表(数据整理日期2022年4月)-IP列表太长只能份2篇发布(1/2)
- 第一部分:基础篇(一)
- pt100阻值温度c语言,pt100温度传感器阻值,pt100温度与阻值对照表
- ARM裸机——FS2410 流水灯
- 日本电视连续剧《阿信》主题歌歌词—永远相信
热门文章
- 【王道操作系统笔记】进程定义组成组织方式特征
- MySQL记录变化工具_MySQL 表记录数对比工具
- 亚马逊出的平板电脑_亚马逊发布Fire HD 8新系列平板电脑,90美元起
- jQuery 查找元素节点
- 购物车ajax php json,Ajax+json实现购物车结算
- layer根据内容动态改变窗口高度
- 【PA2014】【BZOJ3709】Bohater(贪心,排序)
- fcn网络训练代码_FCN网络训练 菜鸟版
- java 父子级json组装不用递归_初级Java程序员如何进阶
- Python入门--集合元素的判断(in,not in集合元素的增加(add()update())集合元素的删除(remove(),discard(),pop(),clear())遍历(for in)