ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
前面我們講到?IOptions?和?IOptionsSnapshot,他們兩個最大的區(qū)別便是前者注冊的是單例模式,后者注冊的是 Scope 模式。而 IOptionsMonitor 則要求配置源必須是可監(jiān)聽的,用來實(shí)現(xiàn) Options 實(shí)例的自動更新,并對外提供了 OnChage 事件,給我們更多的控制權(quán)。
IOptionsMonitor
public interface IOptionsMonitor<out TOptions> {TOptions CurrentValue { get; } ?? ?TOptions Get(string name); ?
? ?IDisposable OnChange(Action<TOptions> listener); }
IOptionsMonitor?與?IOptionsSnapshot?類似,都提供了根據(jù)指定名稱獲取?Options?的功能,并多了一個?OnChange?方法。而它的默認(rèn)實(shí)現(xiàn)者是?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) ? ?{...} }
首先看構(gòu)造函數(shù)中的三個參數(shù),其中?IOptionsFactory<>?和?IOptionsMonitorCache<>?在上一章已講過,而第二個?IOptionsChangeTokenSource<>?則是用來實(shí)現(xiàn)對配置源的監(jiān)聽:
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?重新創(chuàng)建?Options,然后調(diào)用?_onChange?事件。
而?OnChange?方法則用來注冊?_onChange?事件:
public IDisposable OnChange(Action<TOptions> listener){? ?var disposable = new ChangeTrackerDisposable(this, listener);_onChange += disposable.OnChange; ?
? ? ?return disposable; }
這里又使用了一個?OptionsMonitore?的包裝類,用來實(shí)現(xiàn)事件的注銷:
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?的實(shí)現(xiàn)
ConfigurationChangeTokenSource
IConfigurationChangeTokenSource?的默認(rèn)實(shí)現(xiàn)類便是?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?構(gòu)造函數(shù)要求傳入?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?進(jìn)行注冊才可以,當(dāng)然,你也可以實(shí)現(xiàn)自己的?ChangeToken。
總結(jié)
本章介紹了?IOptionsMonitor?的實(shí)現(xiàn):通過?IConfiguration?所提供的?ChangeToken?,來注冊監(jiān)聽事件,對其?CurrentValue?進(jìn)行更新。到此,ASP.NET Core 中的?Options?源碼也就分析完了,其本身比較簡單,并沒有太多東西。更具體的可以去?Github?上看完整的源碼,而 .NET Core 才剛剛發(fā)布了?Preview2?版本,隨時可能會有大的變化,而我也會保持更新,通過觀察每次的變化,也能學(xué)到更多的編程思想,也是一件很快樂的事。
相關(guān)文章:?
ASP.NET Core 源碼學(xué)習(xí)之 Options[1]:Configure
ASP.NET Core 源碼學(xué)習(xí)之 Options[2]:IOptions
ASP.NET Core 源碼學(xué)習(xí)之 Options[3]:IOptionsSnapshot
ASP.NET Core MVC 源碼學(xué)習(xí):詳解 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社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET Core 源码学习之 O
- 下一篇: ASP.NET Core MVC – F