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

上一篇 中,介绍了一下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扩展方法,那是因为在WebHostBuilderBuildCommonServices方法中进行了调用,具体在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实例,然后依次执行IConfigureOptionsConfigure方法,说明最后一次的配置会覆盖之前的配置。而且使用了LazyInitializer来实现双检锁的效果,保证TOptions只实例化一次。

总结

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


相关文章: 

原文地址:http://www.cnblogs.com/RainingNight/p/strongly-typed-options-ioptions-in-asp-net-core.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值