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

前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式。而 IOptionsMonitor 则要求配置源必须是可监听的,用来实现 Options 实例的自动更新,并对外提供了 OnChage 事件,给我们更多的控制权。

目录

  1. IOptionsMonitor
  2. OptionsMonitor源码探索
  3. ConfigurationChangeTokenSource
  4. 示例

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 【转】相关推荐

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

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

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

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

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

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

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

    2017-06-28 更新: OptionsSnapshot 已改为 OptionsManager 变更详情 IOptionsCache 已改为 IOptionsMonitorCache 变更详情 在 ...

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

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

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

    ASP.NET Core 配置系统 在ASP.NET 4.X中,通常将配置存储在 web.config 中,使用静态帮助类来获取这些配置,而对 web.cofng 中进行任何修改时,则会导致应用程序池 ...

  7. ASP.NET Core 源码学习之 Logging[2]:Configure

    在上一章中,我们对 ASP.NET Logging 系统做了一个整体的介绍,而在本章中则开始从最基本的配置开始,逐步深入到源码当中去. 默认配置 在 ASP.NET Core 2.0 中,对默认配置做 ...

  8. ASP.NET Core 源码学习之Logging[1]:Introduction

    在ASP.NET 4.X中,我们通常使用 log4net, NLog 等来记录日志,但是当我们引用的一些第三方类库使用不同的日志框架时,就比较混乱了.而在 ASP.Net Core 中内置了日志系统, ...

  9. ASP.NET Core MVC 源码学习:Routing 路由

    前言 最近打算抽时间看一下 ASP.NET Core MVC 的源码,特此把自己学习到的内容记录下来,也算是做个笔记吧. 路由作为 MVC 的基本部分,所以在学习 MVC 的其他源码之前还是先学习一下 ...

最新文章

  1. 树莓派4与英伟达Jetson Nano性能大比拼,谁是最佳的嵌入式“电脑”?
  2. C语言中的关键字概览
  3. pyQt4 for mac OS 10.8
  4. was not declared in this scope
  5. 洪磊父亲避谈洪磊获释 拘留已过24小时留滞期
  6. Android TextView跑马灯效果与设置文字阴影
  7. Django:ORM基本操作-CRUD,管理器对象objects,----->新增
  8. php中new与构造函数,php - 在构造函数中使用“ new”关键字 - SO中文参考 - www.soinside.com...
  9. mysql 解决慢sql_MySQL被慢sql hang住了,用shell脚本快速清除不断增长的慢sql的办法...
  10. Rust : 红楼梦一书中文字符的统计
  11. 手机客户端接口开发文档模板整理
  12. pe擦除服务器硬盘,老毛桃winpe分区助手删除分区后如何用Gutmann算法擦除硬盘数据?...
  13. 禅道和JIRA大对比
  14. 浩辰云建筑2021功能详细介绍
  15. Java 实现扫雷与高胜率低耗时自动扫雷 AI (下)
  16. 完整的境外、港澳台、电信、移动、联通、教育网、国内其他ISP的IPv4列表(数据整理日期2022年4月)-IP列表太长只能份2篇发布(1/2)
  17. 第一部分:基础篇(一)
  18. pt100阻值温度c语言,pt100温度传感器阻值,pt100温度与阻值对照表
  19. ARM裸机——FS2410 流水灯
  20. 日本电视连续剧《阿信》主题歌歌词—永远相信

热门文章

  1. 【王道操作系统笔记】进程定义组成组织方式特征
  2. MySQL记录变化工具_MySQL 表记录数对比工具
  3. 亚马逊出的平板电脑_亚马逊发布Fire HD 8新系列平板电脑,90美元起
  4. jQuery 查找元素节点
  5. 购物车ajax php json,Ajax+json实现购物车结算
  6. layer根据内容动态改变窗口高度
  7. 【PA2014】【BZOJ3709】Bohater(贪心,排序)
  8. fcn网络训练代码_FCN网络训练 菜鸟版
  9. java 父子级json组装不用递归_初级Java程序员如何进阶
  10. Python入门--集合元素的判断(in,not in集合元素的增加(add()update())集合元素的删除(remove(),discard(),pop(),clear())遍历(for in)