您的位置:首页 > 编程语言 > ASP

ASP.NET Core 源码学习之 Options[2]:IOptions

2017-08-09 07:19 791 查看
在 上一篇 中,介绍了一下Options的注册,而使用时只需要注入 IOption
即可:

public ValuesController(IOptions<MyOptions> options){    var opt = options.Value;
}

IOptions

IOptions 定义非常简单,只有一个
Value
属性:

public interface IOptions<out TOptions> where TOptions : class, new()
{
   TOptions Value { get; }
}

OptionsManager

而当我们注入
IOptions<MyOptions>
时,其默认实现则是
OptionsManager<MyOptions>
,而且使用的单例模式,在
AddOptions
扩展方法中可以看到:

public static IServiceCollection AddOptions(this IServiceCollection services){
   services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>)));    
return services;
}


而我们在使用的时候,并没有调用
AddOptions
扩展方法,那是因为在
WebHostBuilder
BuildCommonServices
方法中进行了调用,具体在Hosting系列中会详细来说。

再看一下
OptionsManager
的源码:

public class OptionsManager<TOptions> : IOptions<TOptions> where TOptions : class, new()
{  
 private LegacyOptionsCache<TOptions> _optionsCache;    
 
 public OptionsManager(IEnumerable<IConfigureOptions<TOptions>> setups)    {
       _optionsCache = new LegacyOptionsCache<TOptions>(setups);
   }  
 
   public virtual TOptions Value
   {      
       get
       {        
         return _optionsCache.Value;
       }
   }
}

OptionsManager
的构造函数中注入了
IConfigureOptions<T>
,而这里使用了 IEnumerable 类型,则表示当注册多个时,则为按顺序依次执行。而其
IConfigureOptions
则在上一篇已经讲过,是通过
Configure
扩展方法进行注册的。而
TOptions
的创建工作则是在
LegacyOptionsCache
类中:

LegacyOptionsCache

先看代码,胜过千言万语:

internal class LegacyOptionsCache<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 LegacyOptionsCache(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);
       }
   }
}

其实非常简单,首先使用默认构造函数创建
TOptions
实例,然后依次执行
IConfigureOptions
Configure
方法,说明最后一次的配置会覆盖之前的配置。而且使用了
LazyInitializer
来实现双检锁的效果,保证
TOptions
只实例化一次。

总结

本文描述了在 .NET Core Options 系统中,IOptions 的使用及实现原理。IOptions 的实现使用的是单例模式,因此当配置源发生变化时,我们无法获取到最新的配置。如果我们希望能够检测到配置源的变化,并能够自动更新,则可以使用 IOptionsSnapshot

相关文章: 

ASP.NET Core 源码学习之 Options[1]:Configure

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跨平台或扫描二维码关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: