ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式。而 IOptionsMonitor 则要求配置源必须是可监听的,用来实现 Options 实例的自动更新,并对外提供了 OnChage 事件,给我们更多的控制权。
IOptionsMonitor
public interface IOptionsMonitor<out TOptions>
{TOptions CurrentValue { get; } TOptions Get(string name); IDisposable OnChange(Action<TOptions> listener);
}
IOptionsMonitor 与 IOptionsSnapshot 类似,都提供了根据指定名称获取 Options
的功能,并多了一个 OnChange
方法。而它的默认实现者是 OptionsMonitor。
public static IServiceCollection AddOptions(this IServiceCollection 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<>)));...
}
OptionsMonitor
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> _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(() => source.GetChangeToken(),() => InvokeChanged());}}
public TOptions CurrentValue { get => Get(Options.DefaultName); } public virtual TOptions Get(string name) => _cache.GetOrAdd(name, () => _factory.Create(name)); private void InvokeChanged() {...} public IDisposable OnChange(Action<TOptions> listener) {...}
}
首先看构造函数中的三个参数,其中 IOptionsFactory<>
和 IOptionsMonitorCache<>
在上一章已讲过,而第二个 IOptionsChangeTokenSource<>
则是用来实现对配置源的监听:
public interface IOptionsChangeTokenSource<out TOptions>
{ IChangeToken GetChangeToken(); string Name { get; }
}
通过 GetChangeToken
获取 ChangeToken , 从而注册其 InvokeChanged
方法:
private void InvokeChanged(){ _cache.TryRemove(Options.DefaultName); var options = CurrentValue; if (_onChange != null){_onChange.Invoke(options);}
}
首先移除 Options 缓存,再通过 IOptionsFactory 重新创建 Options,然后调用 _onChange
事件。
而 OnChange 方法则用来注册 _onChange
事件:
public IDisposable OnChange(Action<TOptions> listener){
var disposable = new ChangeTrackerDisposable(this, listener);_onChange += disposable.OnChange; return disposable;
}
这里又使用了一个 OptionsMonitore 的包装类,用来实现事件的注销:
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;
}
再去看一下 IConfigurationChangeTokenSource 的实现
ConfigurationChangeTokenSource
IConfigurationChangeTokenSource 的默认实现类便是 ConfigurationChangeTokenSource<>
:
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config) where TOptions : class{...services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, config));...
}
ConfigurationChangeTokenSource 构造函数要求传入 IConfiguration,其而 ChangeToken
的获取便是通过 IConfiguration 来得到的:
public interface IConfiguration{... IChangeToken GetReloadToken();...
}
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();}
}
因此要想使用 IOptionsMonitor,必须要使用 IConfiguration 进行注册才可以,当然,你也可以实现自己的 ChangeToken
。
总结
本章介绍了 IOptionsMonitor
的实现:通过 IConfiguration 所提供的 ChangeToken
,来注册监听事件,对其 CurrentValue
进行更新。到此,ASP.NET Core 中的 Options 源码也就分析完了,其本身比较简单,并没有太多东西。更具体的可以去 Github 上看完整的源码,而 .NET Core 才刚刚发布了 Preview2
版本,随时可能会有大的变化,而我也会保持更新,通过观察每次的变化,也能学到更多的编程思想,也是一件很快乐的事。
相关文章:
ASP.NET Core 源码学习之 Options[1]:Configure
ASP.NET Core 源码学习之 Options[2]:IOptions
ASP.NET Core 源码学习之 Options[3]:IOptionsSnapshot
ASP.NET Core MVC 源码学习:详解 Action 的匹配
asp.net core源码飘香:从Hosting开始
asp.net core源码飘香:Configuration组件
asp.net core源码飘香:Options组件
asp.net core源码飘香:Logging组件
原文地址:http://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-monitor-in-asp-net-core.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
ASP.NET Core 源码学习之 Options[4]: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源码飘香:Options组件
简介: Options组件是一个小组件,但用的地方很多.它本质是将一个POCO类注册到容器中(主要在Startup中作为其他组件的配置功能提供),后续使用的时候就可以通过比如构造函数注入等获取到POC ...
- ASP.NET Core源码学习(一)Hosting
ASP.NET Core源码的学习,我们从Hosting开始, Hosting的GitHub地址为:https://github.com/aspnet/Hosting.git 朋友们可以从以上链接克隆 ...
- ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor 【转】
原文链接:https://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-monitor-in-asp-net-core. ...
- ASP.NET Core 源码学习之 Logging[3]:Logger
上一章,我们介绍了日志的配置,在熟悉了配置之后,自然是要了解一下在应用程序中如何使用,而本章则从最基本的使用开始,逐步去了解去源码. LoggerFactory 我们可以在构造函数中注入 ILogge ...
最新文章
- 赠书:全球首本VS Code中文书来了,高效编程秘诀全收录!
- 【竞赛经验分享】2020腾讯广告算法大赛:如何突破分数瓶颈?
- [BZOJ 1500] [NOI2005] 维修数列
- 这才是真正的Git——Git内部原理揭秘!
- android 解析雅虎天气
- 的内怎么放_放了心脏支架能活多久?医生坦言:做到三件事,才能和正常人一样...
- 网络安全-使用HTTP动词篡改的认证旁路
- 史上最简单的决策树模型讲解
- mfc文字闪烁如何解决_男同胞福音!如何解决尿尿时最尴尬的难题?建议偷偷收藏(文字版)...
- 6-1 稀疏矩阵求和 (70 分)
- 下列有关计算机系统叙述正确,()下列有关计算机系统软件的叙述正确的是____
- 小米净水器更换php教程,这种方法更换滤芯寿命更长:小米净水器
- python怎么爬取知乎回答并制作词云_使用python爬取流浪地球影评并制作词云,看看别人都说了些说什么...
- 科技文献检索的途径、方法和步骤 - 易智编译 EaseEditing
- Easy ip 简单配置实验
- 淘宝客?CPS技术是怎么实现的?
- influence和effect的区别
- 为App界面添加蒙层效果
- Docker容器网络代理设置
- alot英文怎么读_lots是什么意思_lots怎么读_lots翻译_用法_发音_词组_同反义词_签( lot的名词复数 )-新东方在线英语词典...
热门文章
- MongoDB 3.0 新增特性一览
- 用仿ActionScript的语法来编写html5——终篇,LegendForHtml5Programming1.0开源库件
- LateUpdate、Late、FixedUpdate的意义
- lost connection to MySQL server at waiting for initial communication packet,system error:o
- Android MediaScanner:(一)MediaScanner总体架构
- Event Logging 技术简介(转载)
- cacti+nagios 整合遇到的问题
- perl对文件和目录进行操作
- 怎么实现动态设置静态文件存储目录?
- MD5计算,一个扩展类,哪里都能用