ASP.NET Core 源码学习之 Options[3]:IOptionsSnapshot

2017-06-28 更新:
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参数,我想大家便会想到在 第一章 中所介绍的指定NameConfigure方法,这便是它的用武之地了,通过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 cachereturn _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跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

layui结合ajax实现下拉联动效果

大家好好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号&#xff1a;雄雄的小课堂。 昨天分享的是使用layui集合springboot实现图片上传&#xff0c;文章地址在这里&#xff0c;需要的小伙伴们可以去看看&#xff1a; 今天给大家分享的内容也是那天在造项目的时候完成的&am…

ASP.NET Core MVC – Caching Tag Helpers

简介 缓存可以大大提高应用程序加载时间和响应速度。我们可以使用缓存Tag Helpers缓存不会频繁更改的HTML内容。 在上一篇文章ASP.NET Core MVC Tag Helpers 介绍中&#xff0c;我们谈到了Tag Helpers&#xff0c;演示Tag Helpers能做什么、如何使用它们以及一些最常用的Tag …

layui结合ajax实现下拉菜单联动效果

大家好好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号&#xff1a;雄雄的小课堂。昨天分享的是使用layui集合springboot实现图片上传&#xff0c;文章地址在这里&#xff0c;需要的小伙伴们可以去看看&#xff1a;今天给大家分享的内容也是那天在造项目的时候完成的&#x…

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

前面我们讲到 IOptions 和 IOptionsSnapshot&#xff0c;他们两个最大的区别便是前者注册的是单例模式&#xff0c;后者注册的是 Scope 模式。而 IOptionsMonitor 则要求配置源必须是可监听的&#xff0c;用来实现 Options 实例的自动更新&#xff0c;并对外提供了 OnChage 事件…

Layui hint: Table element property lay-data configuration item has a syntax error解决方式

今天在使用layui的数据表格时&#xff0c;报错Layui hint: Table element property lay-data configuration item has a syntax error&#xff0c;找了好几中解决方式&#xff0c;网上说的用{}括起来。 对于我来说都不适应哎&#xff0c;我发现我的问题比较低级。 源代码&…

ASP.NET Core MVC – Form Tag Helpers

简介 我们已经介绍过Tag Helpers以及一些最常用的Tag Helpers&#xff0c;也谈到了缓存Tag Helpers。在这篇文章中&#xff0c;我们将讨论表单Tag Helpers。 HTML或Web表单通过使用各种HTML元素用于收集来自用户的输入&#xff0c;如输入框、复选框、单选按钮、下拉列表等。使…

表单提交报错405的解决方式

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号&#xff1a;雄雄的小课堂。今天&#xff0c;分享一个bug的解决的方法&#xff0c;到最后解决了也不知道为啥这样是可以的&#xff0c;原来的方法是不可以的……01问题描述项目中有这样的一个需求&#xff0c;就是在原来的…

JavaFX图表(二)之饼图

翻译自 JavaFX - 饼图 饼图是将值表示为具有不同颜色的圆的切片。标记这些切片&#xff0c;并且在图表中表示与每个切片对应的值。 以下是一张饼图&#xff0c;描绘了一个实例中各公司的移动销售情况。 在JavaFX中&#xff0c;饼图由名为PieChart的类表示。该类属于包javaf…

RabbitMQ(mall项目学习 死信、延迟队列)

文章目录RabbitMQ的死信队列RabbitMQ的延迟队列mall项目 业务场景说明Rabbitmq 插件实现延迟队列启动&#xff08; UI 界面 &#xff09;RabbitMQ的死信队列 TTL&#xff1a;time to live 消息存活时间 如果消息在存活时间内未被消费&#xff0c;则会被清除 RabbitMQ⽀持两种…

asp.net中条件查询+分页

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号&#xff1a;雄雄的小课堂。 今天&#xff0c;分享的是asp.net中条件查询分页的小案例。 如下图所示&#xff1a; 各个功能模块均已标注&#xff0c;先大致介绍一下业务。 \1. 点击左侧图书类别&#xff0c;根绝类别编…

.NET Standard@Xamarin.Forms

编者语 &#xff1a; .NET技术社群由于微软的开源和跨平台性越来越受关注&#xff0c;但国内都是碍于大家以往的认识阻碍了发展&#xff0c;没有太多大的企业敢于去把.NET作为第一生产力。你作为.NET程序员有义务去保护好你的饭碗&#xff0c;也要改变人对.NET的认知。希望大家…

JavaFX图表(一)

翻译自 JavaFX - 图表 通常&#xff0c;图表是数据的图形表示。有各种各样的图表来表示数据&#xff0c;如条形图&#xff0c;饼图&#xff0c;折线图&#xff0c;散点图等。 JavaFX支持各种饼图和XY图表。在XY平面上表示的图表包括AreaChart&#xff0c;BarChart&#xff0…

我们在进行着一场拔河比赛……

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。不知不觉&#xff0c;3班已经面临就业了。似乎每个班级到三期的最后阶段&#xff0c;出现的问题都那么类似&#xff0c;那就是一部分同学已经“放弃努力”了&#xff0c;大家貌似在等着最后的就业&…

JavaFX图表(三)之折线图

翻译自 JavaFX - 折线图 折线图或折线图将信息显示为由直线段连接的一系列数据点&#xff08;标记&#xff09;。折线图显示数据如何以相等的时间频率变化。 以下是描绘不同年份学校数量的折线图。 在JavaFX中&#xff0c;折线图由名为LineChart的类表示。该类属于包javafx…

释放.NET Big Memory和内存映射文件的能量

要点&#xff1a; 通常Web服务器具有的内存远远超过了.NET GC在正常情况下可以有效处理的量。缓存服务器的性能优势通常会因增加了网络成本而下降。内存映射文件通常是在系统重新启动后填充缓存的最快方式。服务器端调优的目的是出站网络连接达到饱和的程度。 通过最小化CPU、…

3班的第二次模拟面试

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。今天&#xff0c;三班进行了第二次模拟面试&#xff0c;还是和第一次一样&#xff0c;分为技术面试和人事面试&#xff0c;不过这次不一样的一点就是我亲自面的大部分开发学生。通过这次模拟面试&#…

JavaFX图表(四)之面积图

翻译自 JavaFX - 面积图 面积图用于绘制基于区域的图表。它绘制给定系列点与轴之间的区域。通常&#xff0c;此图表用于比较两个数量。 以下是一张区域图表&#xff0c;描绘了一个星期内两个人消耗的水果数量。 在JavaFX中&#xff0c;Area图表由名为AreaChart的类表示。该类…

深入聊聊微服务架构的身份认证问题

从单体应用架构到分布式应用架构再到微服务架构&#xff0c;应用的安全访问在不断的经受考验。为了适应架构的变化、需求的变化&#xff0c;身份认证与鉴权方案也在不断的变革。面对数十个甚至上百个微服务之间的调用&#xff0c;如何保证高效安全的身份认证&#xff1f;面对外…

今晚在学校值班……

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。今晚在学校值班。每次进班巡查的时候&#xff0c;不管是哪个班级&#xff0c;同学们个个都是精神抖擞&#xff0c;双眼紧盯屏幕&#xff0c;双手放在键盘上&#xff0c;看起来貌似正在打代码或思考似的…

JavaFX图表(五)之气泡图

翻译自 JavaFX - 气泡图 气泡图用于种植三维数据; 第三个维度将由气泡的大小&#xff08;半径&#xff09;表示。 以下是描绘完成工作的气泡图。 在JavaFX中&#xff0c;气泡图由名为BubbleChart的类表示。该类属于包javafx.scene.chart。通过实例化此类&#xff0c;您可以…