首页 > 学院 > 开发设计 > 正文

[Asp.net5]Options-配置文件(2)

2019-11-14 14:31:01
字体:
来源:转载
供稿:网友

很久之前写过一篇介绍Options的文章,2016年再打开发现很多变化。增加了新类,增加OptionMonitor相关的类。今天就对于这个现在所谓的新版本进行介绍。

老版本的传送门([asp.net 5] Options-配置文件之后昂的配置)。

首先上一个图:

*绿线是继承关系,蓝线是关联关系。

我们把上面切成2大部分。

Option部分

这部分分为俩部分,第一部分直接创建Options,该部分通过Options静态类创建一个OptionsWrapper类,之后将(IOptions,OptionsWrapper)进行注入。这部分是DI的实体注入,很简单,没有什么可说的,此处应用非常常见的“工厂模式”。

第二部分是将(IOptions,OptionsManager)进行注入。我们OptionsManager会使用IEnumerable<IConfigureOptions<TOptions>>作为参数,而内部返回的是OptionsCache类型的对象,此处应用非常常见的“代理模式

    internal class OptionsCache<TOptions> where TOptions : class, new()    {        PRivate readonly Func<TOptions> _createCache;        private object _cacheLock = new object();        private bool _cacheInitialized;        private TOptions _options;        private IEnumerable<IConfigureOptions<TOptions>> _setups;        public OptionsCache(IEnumerable<IConfigureOptions<TOptions>> setups)        {            _setups = setups;            _createCache = CreateOptions;        }        private TOptions CreateOptions()        {            var result = new TOptions();            if (_setups != null)            {                foreach (var setup in _setups)                {                    setup.Configure(result);                }            }            return result;        }        public virtual TOptions Value        {            get            {                return LazyInitializer.EnsureInitialized(                    ref _options,                    ref _cacheInitialized,                    ref _cacheLock,                    _createCache);            }        }    }
OptionsCache

此处附录OptionsCache代码,里面(IConfigureOptions,ConfigureOptions)已经进行注入了。而ConfigureOptions代码如下:

    public class ConfigureOptions<TOptions> : IConfigureOptions<TOptions> where TOptions : class    {        public ConfigureOptions(Action<TOptions> action)        {            if (action == null)            {                throw new ArgumentNullException(nameof(action));            }            Action = action;        }        public Action<TOptions> Action { get; private set; }        public virtual void Configure(TOptions options)        {            if (options == null)            {                throw new ArgumentNullException(nameof(options));            }            Action.Invoke(options);        }    }
ConfigureOptions

而ConfigureOptions实际上只是对Action<TOptions>的封装吧了(这里是不是可以理解为适配器)。

*为什么要传递Action<T>进行配置?我的理解是因为延时性延时的概念就是,你做的修改不是立马生效,以至于配置的时候,我们都不用考虑先后顺序。

OptionsMonitor部分

OptionsMonitor是对Options的监视器。我决定这部分好像一个调度者模式??

IOptionsChangeTokenSource

OptionsMonitor代码如下:

    public class OptionsMonitor<TOptions> : IOptionsMonitor<TOptions> where TOptions : class, new()    {        private OptionsCache<TOptions> _optionsCache;        private readonly IEnumerable<IConfigureOptions<TOptions>> _setups;        private readonly IEnumerable<IOptionsChangeTokenSource<TOptions>> _sources;        public OptionsMonitor(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IOptionsChangeTokenSource<TOptions>> sources)        {            _sources = sources;            _setups = setups;            _optionsCache = new OptionsCache<TOptions>(setups);        }        public TOptions CurrentValue        {            get            {                return _optionsCache.Value;            }        }        public IDisposable OnChange(Action<TOptions> listener)        {            var disposable = new ChangeTrackerDisposable();            foreach (var source in _sources)            {                Action<object> callback = null;                IDisposable previousSubscription = null;                callback = (s) =>                {                    // The order here is important. We need to take the token and then apply our changes BEFORE                    // registering. This prevents us from possible having two change updates to process concurrently.                    //                    // If the token changes after we take the token, then we'll process the update immediately upon                    // registering the callback.                    var token = source.GetChangeToken();                    // Recompute the options before calling the watchers                    _optionsCache = new OptionsCache<TOptions>(_setups);                    listener(_optionsCache.Value);                    // Remove the old callback after its been fired                    var nextSubscription = token.RegisterChangeCallback(callback, s);                    disposable.Disposables.Add(nextSubscription);                    disposable.Disposables.Remove(previousSubscription);                    previousSubscription = nextSubscription;                };                previousSubscription = source.GetChangeToken().RegisterChangeCallback(callback, state: null);                disposable.Disposables.Add(previousSubscription);            }            return disposable;        }    }
OptionsMonitor

通过IOptionsChangeTokenSource的IChangeToken对象发出更改请求,之后Action<TOptions> listener进行数据更改。

Onchange方法,实现上就是每次调用都会创建一个新的IDisposable(ChangeTrackerDisposable),如此而已。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表