前面我们讲到 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相关推荐

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

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

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

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

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

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

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

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

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

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

  6. asp.net core源码飘香:Options组件

    简介: Options组件是一个小组件,但用的地方很多.它本质是将一个POCO类注册到容器中(主要在Startup中作为其他组件的配置功能提供),后续使用的时候就可以通过比如构造函数注入等获取到POC ...

  7. ASP.NET Core源码学习(一)Hosting

    ASP.NET Core源码的学习,我们从Hosting开始, Hosting的GitHub地址为:https://github.com/aspnet/Hosting.git 朋友们可以从以上链接克隆 ...

  8. ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor 【转】

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

  9. ASP.NET Core 源码学习之 Logging[3]:Logger

    上一章,我们介绍了日志的配置,在熟悉了配置之后,自然是要了解一下在应用程序中如何使用,而本章则从最基本的使用开始,逐步去了解去源码. LoggerFactory 我们可以在构造函数中注入 ILogge ...

最新文章

  1. 赠书:全球首本VS Code中文书来了,高效编程秘诀全收录!
  2. 【竞赛经验分享】2020腾讯广告算法大赛:如何突破分数瓶颈?
  3. [BZOJ 1500] [NOI2005] 维修数列
  4. 这才是真正的Git——Git内部原理揭秘!
  5. android 解析雅虎天气
  6. 的内怎么放_放了心脏支架能活多久?医生坦言:做到三件事,才能和正常人一样...
  7. 网络安全-使用HTTP动词篡改的认证旁路
  8. 史上最简单的决策树模型讲解
  9. mfc文字闪烁如何解决_男同胞福音!如何解决尿尿时最尴尬的难题?建议偷偷收藏(文字版)...
  10. 6-1 稀疏矩阵求和 (70 分)
  11. 下列有关计算机系统叙述正确,()下列有关计算机系统软件的叙述正确的是____
  12. 小米净水器更换php教程,这种方法更换滤芯寿命更长:小米净水器
  13. python怎么爬取知乎回答并制作词云_使用python爬取流浪地球影评并制作词云,看看别人都说了些说什么...
  14. 科技文献检索的途径、方法和步骤 - 易智编译 EaseEditing
  15. Easy ip 简单配置实验
  16. 淘宝客?CPS技术是怎么实现的?
  17. influence和effect的区别
  18. 为App界面添加蒙层效果
  19. Docker容器网络代理设置
  20. alot英文怎么读_lots是什么意思_lots怎么读_lots翻译_用法_发音_词组_同反义词_签( lot的名词复数 )-新东方在线英语词典...

热门文章

  1. MongoDB 3.0 新增特性一览
  2. 用仿ActionScript的语法来编写html5——终篇,LegendForHtml5Programming1.0开源库件
  3. LateUpdate、Late、FixedUpdate的意义
  4. lost connection to MySQL server at waiting for initial communication packet,system error:o
  5. Android MediaScanner:(一)MediaScanner总体架构
  6. Event Logging 技术简介(转载)
  7. cacti+nagios 整合遇到的问题
  8. perl对文件和目录进行操作
  9. 怎么实现动态设置静态文件存储目录?
  10. MD5计算,一个扩展类,哪里都能用