ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)
2020-01-14 10:09
405 查看
前言
IOptionsMonitor 是一种单一示例服务,可随时检索当前选项值,这在单一实例依赖项中尤其有用。IOptionsMonitor用于检索选项并管理TOption实例的选项通知, IOptionsMonitor 支持以下方案:
- 更改通知
- 命名选项
- 可重载配置
- 选择性选项失效 (IOptionsMonitorCache)
IOptionsMonitor
public interface IOptionsMonitor<out TOptions> { /// <summary> /// 返回具有 DefaultName 的当前 TOptions 实例。 /// </summary> TOptions CurrentValue { get; } /// <summary> /// 返回具有给定名称的已配置的 TOptions 实例。 /// </summary> TOptions Get(string name); /// <summary> /// 注册一个要在命名 TOptions 更改时调用的侦听器。 /// </summary> IDisposable OnChange(Action<TOptions, string> listener); }
OptionsMonitor
OptionsMonitor通过IOptionsChangeTokenSource实现监听事件
public class OptionsMonitor<TOptions> : IOptionsMonitor<TOptions>, IDisposable where TOptions : class, new() { private readonly IOptionsMonitorCache<TOptions> _cache; private readonly IOptionsFactory<TOptions> _factory; private readonly IEnumerable<IOptionsChangeTokenSource<TOptions>> _sources; private readonly List<IDisposable> _registrations = new List<IDisposable>(); internal event Action<TOptions, string> _onChange; /// <summary> /// Constructor. /// </summary> /// <param name="factory">The factory to use to create options.</param> /// <param name="sources">The sources used to listen for changes to the options instance.</param> /// <param name="cache">The cache used to store options.</param> public OptionsMonitor(IOptionsFactory<TOptions> factory, IEnumerable<IOptionsChangeTokenSource<TOptions>> sources, IOptionsMonitorCache<TOptions> cache) { _factory = factory; _sources = sources; _cache = cache; foreach (var source in _sources) { var registration = ChangeToken.OnChange( () => source.GetChangeToken(), (name) => InvokeChanged(name), source.Name); _registrations.Add(registration); } } private void InvokeChanged(string name) { name = name ?? Options.DefaultName; _cache.TryRemove(name); var options = Get(name); if (_onChange != null) { _onChange.Invoke(options, name); } }/// <summary> /// The present value of the options. /// </summary> public TOptions CurrentValue { get => Get(Options.DefaultName); } /// <summary> /// Returns a configured <typeparamref name="TOptions"/> instance with the given <paramref name="name"/>. /// </summary> public virtual TOptions Get(string name) { name = name ?? Options.DefaultName; return _cache.GetOrAdd(name, () => _factory.Create(name)); } /// <summary> /// Registers a listener to be called whenever <typeparamref name="TOptions"/> changes. /// </summary> /// <param name="listener">The action to be invoked when <typeparamref name="TOptions"/> has changed.</param> /// <returns>An <see cref="IDisposable"/> which should be disposed to stop listening for changes.</returns> public IDisposable OnChange(Action<TOptions, string> listener) { var disposable = new ChangeTrackerDisposable(this, listener); _onChange += disposable.OnChange; return disposable; } /// <summary> /// Removes all change registration subscriptions. /// </summary> public void Dispose() { // Remove all subscriptions to the change tokens foreach (var registration in _registrations) { registration.Dispose(); } _registrations.Clear(); } internal class ChangeTrackerDisposable : IDisposable { private readonly Action<TOptions, string> _listener; private readonly OptionsMonitor<TOptions> _monitor; public ChangeTrackerDisposable(OptionsMonitor<TOptions> monitor, Action<TOptions, string> listener) { _listener = listener; _monitor = monitor; } public void OnChange(TOptions options, string name) => _listener.Invoke(options, name); public void Dispose() => _monitor._onChange -= OnChange; } }
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, string> listener) { var disposable = new ChangeTrackerDisposable(this, listener); _onChange += disposable.OnChange; return disposable; }
通过ChangeTrackerDisposable进行事件的注销
internal class ChangeTrackerDisposable : IDisposable { private readonly Action<TOptions, string> _listener; private readonly OptionsMonitor<TOptions> _monitor; public ChangeTrackerDisposable(OptionsMonitor<TOptions> monitor, Action<TOptions, string> listener) { _listener = listener; _monitor = monitor; } public void OnChange(TOptions options, string name) => _listener.Invoke(options, name); public void Dispose() => _monitor._onChange -= OnChange; }
ConfigurationChangeTokenSource
ConfigurationChangeTokenSource实现IOptionsChangeTokenSource接口
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; Name = name ?? Options.DefaultName; } public string Name { get; } public IChangeToken GetChangeToken() { return _config.GetReloadToken(); } }
示例
public class WeatherForecastController : ControllerBase { private readonly ILogger<WeatherForecastController> _logger; private readonly IOptionsMonitor<MyOptions> _options; public WeatherForecastController(IOptionsMonitor<MyOptions> options, ILogger<WeatherForecastController> logger) { _options = options; _logger = logger; } [HttpGet] public OkObjectResult Get() { _options.OnChange(_=>_logger.LogWarning(_options.CurrentValue.Name)); return Ok(string.Format("Name:{0},Url:{1}", _options.CurrentValue.Name,_options.CurrentValue.Url)); } }
现在我们每次修改配置文件,便会触发OnChange事件
- 点赞 1
- 收藏
- 分享
- 文章举报
相关文章推荐
- ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)
- ASP.NET Core 选项模式源码学习Options IOptions(二)
- ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
- ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor
- ASP.NET Core 选项模式源码学习Options Configure(一)
- ASP.NET Core 2.1 源码学习之 Options[1]:Configure
- ASP.NET Core 2.1 源码学习之 Options[2]:IOptions
- ASP.NET Core 源码学习之 Options[2]:IOptions
- (13)ASP.NET Core 中的选项模式(Options)
- ASP.NET Core 源码学习之 Options[1]:Configure
- ASP.NET Core 源码学习之 Options[3]:IOptionsSnapshot
- [ASP.NET Core 3框架揭秘] Options[2]: 配置选项的正确使用方式[下篇]
- ASP.NET Core 源码学习之 Logging[2]:Configure
- ASP.NET Core 源码学习之 Logging[1]:Introduction
- ASP.NET Core 源码学习之 Logging[2]:Configure
- ASP.NET Core 源码学习之Logging[1]:Introduction
- 【ASP.NET Core 】ASP.NET Core 源码学习之 Logging[1]:Introduction
- ASP.NET Core 源码学习之 Logging[3]:Logger
- ASP.NET Core 源码学习之 Logging[4]:FileProvider
- asp.net core 3.0 选项模式1:使用