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擴展方法,那是因為在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跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的ASP.NET Core 源码学习之 Options[2]:IOptions的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#和NewSQL更配 —— Cockr
- 下一篇: ASP.NET Core MVC Tag