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

来源:互联网 发布:淘宝商品怎么下架 编辑:程序博客网 时间:2024/06/05 12:49

前面我们讲到 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跨平台或扫描二维码关注

阅读全文
0 0
原创粉丝点击