ASP.NET Core 源码学习之 Options[3]:IOptionsSnapshot
2017-08-10 07:07
1111 查看
2017-06-28 更新:
OptionsSnapshot 已改为 OptionsManager 变更详情
IOptionsCache 已改为 IOptionsMonitorCache 变更详情
在 上一章 中,介绍了 IOptions 的使用, 而我们知道,在 ConfigurationBuilder 的 AddJsonFile 中,有一个 reloadOnChange 参数,设置为 true 时,在配置文件发生变化时,会自动更新 IConfigurationRoot ,这是一个非常棒的特性,遗憾的是 IOptions 在配置源发生变化时,并不会进行更新。好在,微软还为我们提供了 IOptionsSnapshot ,本章就来探索一下其源码。
看到
那 IOptionsSnapshot 又是如何实现配置的同步的呢?别急,先看一下它与 IOption 的区别:
首先很明显的是:一个是单例,一个指定作用域。其次,IOptionsSnapshot 的实现者是
代码很简单,Options 的创建是通过
IOptionsFactory 的默认实现类是
相关文章:
ASP.NET Core 源码学习之 Options[1]:Configure
ASP.NET Core 源码学习之 Options[2]:IOptions
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-in-asp-net-core.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
OptionsSnapshot 已改为 OptionsManager 变更详情
IOptionsCache 已改为 IOptionsMonitorCache 变更详情
在 上一章 中,介绍了 IOptions 的使用, 而我们知道,在 ConfigurationBuilder 的 AddJsonFile 中,有一个 reloadOnChange 参数,设置为 true 时,在配置文件发生变化时,会自动更新 IConfigurationRoot ,这是一个非常棒的特性,遗憾的是 IOptions 在配置源发生变化时,并不会进行更新。好在,微软还为我们提供了 IOptionsSnapshot ,本章就来探索一下其源码。
IOptionsSnapshot
IOptionsSnapshot 继承自IOptions,并扩展了一个
Get方法:
public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions> where TOptions : class, new() { TOptions Get(string name); }
看到
Get方法的
Name参数,我想大家便会想到在 第一章 中所介绍的指定
Name的
Configure方法,这便是它的用武之地了,通过
Name的不同,来配置同一
Options类型的多个实例。
那 IOptionsSnapshot 又是如何实现配置的同步的呢?别急,先看一下它与 IOption 的区别:
services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>))); services.TryAdd(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsSnapshot<>)));
首先很明显的是:一个是单例,一个指定作用域。其次,IOptionsSnapshot 的实现者是
OptionsSnapshot。
OptionsSnapshot
从名字上来看,便知道它保存的只是一份快照,先看下源码:public class OptionsSnapshot<TOptions> : IOptionsSnapshot<TOptions> where TOptions : class, new() { private readonly IOptionsFactory<TOptions> _factory; private readonly OptionsCache<TOptions> _cache = new OptionsCache<TOptions>(); public OptionsSnapshot(IOptionsFactory<TOptions> factory) { _factory = factory; } public TOptions Value => Get(Options.DefaultName); public virtual TOptions Get(string name) { if (name == null) { throw new ArgumentNullException(nameof(name)); } // Store the options in our instance cache return _cache.GetOrAdd(name, () => _factory.Create(name)); } }
代码很简单,Options 的创建是通过
IOptionsFactory来实现的,而 Options 的实例是通过
OptionsCache来保存的。那便去看下他们的源码。
IOptionsFactory
public interface IOptionsFactory<TOptions> where TOptions : class, new() { TOptions Create(string name); } public class OptionsFactory<TOptions> : IOptionsFactory<TOptions> where TOptions : class, new() { private readonly IEnumerable<IConfigureOptions<TOptions>> _setups; private readonly IEnumerable<IPostConfigureOptions<TOptions>> _postConfigures; public OptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IPostConfigureOptions<TOptions>> postConfigures) { _setups = setups; _postConfigures = postConfigures; } public TOptions Create(string name) { var options = new TOptions(); foreach (var setup in _setups) { if (setup is IConfigureNamedOptions<TOptions> namedSetup) { namedSetup.Configure(name, options); } else if (name == Options.DefaultName) { setup.Configure(options); } } foreach (var post in _postConfigures) { post.PostConfigure(name, options); } return options; } }
IOptionsFactory 的默认实现类是
OptionsFactory,在创建
Options时,先执行所有的
Configure方法,然后执行
PostConfigure方法。在 第一章 中讲的
PostConfigure方法,也在这里派上用场了。
OptionsCache
OptionsCache 用来缓存 Options 的实例,相当于一个优化的Options字典,并使用
Lazy实现了延迟初始化,看代码:
public class OptionsCache<TOptions> : IOptionsCache<TOptions> where TOptions : class{ private readonly ConcurrentDictionary<string, Lazy<TOptions>> _cache = new ConcurrentDictionary<string, Lazy<TOptions>>(StringComparer.Ordinal); public virtual TOptions GetOrAdd(string name, Func<TOptions> createOptions) { if (name == null) throw new ArgumentNullException(nameof(name)); if (createOptions == null) throw new ArgumentNullException(nameof(createOptions)); return _cache.GetOrAdd(name, new Lazy<TOptions>(createOptions)).Value; } public virtual bool TryAdd(string name, TOptions options) { if (name == null) throw new ArgumentNullException(nameof(name)); if (options == null) throw new ArgumentNullException(nameof(options)); return _cache.TryAdd(name, new Lazy<TOptions>(() => options)); } public virtual bool TryRemove(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); return _cache.TryRemove(name, out var ignored); } }
总结
IOptionsSnapshot 通过注册为一个作用域内的单例模式,来保证当配置发生变化时,下一个请求可以获取到最新的配置。其实在2.0-preview2中,OptionsSnapshot 使用了 IOptionsChangeTokenSource 模式,来监听配置的变化,当发生变化清空 OptionsCache 中的缓存,来实现 Options 的自动更新。当时我还感到困扰:“OptionsSnapshot既然能够做到配置的更新,怎么还注册成
Scope实例呢?”。而现在缺少了 IOptionsChangeTokenSource 模式的即时更新,或许让我们感觉不是那么爽,当然也有一个致命的问题,就是当我们在一个自定义的类中使用了 IOptionsSnapshot ,并且这个类本身是以单例的形式注册的,那么便永远获取不到最新的配置了。不过,我们还有最后一个大杀器: IOptionsMonitor,来满足我们极致的需求,哈哈,下一篇就来介绍一下它。
相关文章:
ASP.NET Core 源码学习之 Options[1]:Configure
ASP.NET Core 源码学习之 Options[2]:IOptions
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-in-asp-net-core.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
相关文章推荐
- ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
- ASP.NET Core 源码学习之 Options[1]:Configure
- ASP.NET Core 源码学习之 Options[2]:IOptions
- ASP.NET Core 2.1 源码学习之 Options[2]:IOptions
- ASP.NET Core 2.1 源码学习之 Options[1]:Configure
- ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor
- ASP.NET Core 源码学习之 Logging[3]:Logger
- ASP.NET Core 源码学习之 Logging[2]:Configure
- ASP.NET Core 源码学习之 Logging[4]:FileProvider
- ASP.NET Core 源码学习之Logging[1]:Introduction
- ASP.NET Core 源码学习之 Logging[1]:Introduction
- asp.net core源码飘香:Options组件
- ASP.NET Core 源码学习之 Logging[2]:Configure
- 【ASP.NET Core 】ASP.NET Core 源码学习之 Logging[1]:Introduction
- ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]
- Asp.net Core学习文章
- asp.net core合并压缩资源文件引发的学习之旅
- ASP.NET Core 一步步搭建个人网站微信H5房卡三公棋牌源码下载_Linux系统移植
- 这应该是目前最快速有效的ASP.NET Core学习方式(视频)
- 这应该是目前最快速有效的ASP.NET Core学习方式(视频)