[Asp.net 5] Options-配置文件(2)

来源:http://www.cnblogs.com/watermoon2/archive/2016/01/10/5119085.html
-Advertisement-
Play Games

很久之前寫過一篇介紹Options的文章,2016年再打開發現很多變化。增加了新類,增加OptionMonitor相關的類。今天就對於這個現在所謂的新版本進行介紹。老版本的傳送門([Asp.net 5] Options-配置文件之後昂的配置)。首先上一個圖:*綠線是繼承關係,藍線是關聯關係。我們把上...


很久之前寫過一篇介紹Options的文章,2016年再打開發現很多變化。增加了新類,增加OptionMonitor相關的類。今天就對於這個現在所謂的新版本進行介紹。

老版本的傳送門([Asp.net 5] Options-配置文件之後昂的配置)。

首先上一個圖:

*綠線是繼承關係,藍線是關聯關係。

我們把上面切成2大部分。

Option部分

這部分分為倆部分,第一部分直接創建Options,該部分通過Options靜態類創建一個OptionsWrapper類,之後將(IOptions,OptionsWrapper)進行註入。這部分是DI的實體註入,很簡單,沒有什麼可說的,此處應用非常常見的“工廠模式”。

第二部分是將(IOptions,OptionsManager)進行註入。我們OptionsManager會使用IEnumerable<IConfigureOptions<TOptions>>作為參數,而內部返回的是OptionsCache類型的對象,此處應用非常常見的“代理模式

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

此處附錄OptionsCache代碼,裡面(IConfigureOptions,ConfigureOptions)已經進行註入了。而ConfigureOptions代碼如下:

    public class ConfigureOptions<TOptions> : IConfigureOptions<TOptions> where TOptions : class
    {
        public ConfigureOptions(Action<TOptions> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            Action = action;
        }

        public Action<TOptions> Action { get; private set; }

        public virtual void Configure(TOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            Action.Invoke(options);
        }
    }
ConfigureOptions

而ConfigureOptions實際上只是對Action<TOptions>的封裝吧了(這裡是不是可以理解為適配器)。

*為什麼要傳遞Action<T>進行配置?我的理解是因為延時性延時的概念就是,你做的修改不是立馬生效,以至於配置的時候,我們都不用考慮先後順序。

OptionsMonitor部分

OptionsMonitor是對Options的監視器。我決定這部分好像一個調度者模式??

IOptionsChangeTokenSource

OptionsMonitor代碼如下:

    public class OptionsMonitor<TOptions> : IOptionsMonitor<TOptions> where TOptions : class, new()
    {
        private OptionsCache<TOptions> _optionsCache;
        private readonly IEnumerable<IConfigureOptions<TOptions>> _setups;
        private readonly IEnumerable<IOptionsChangeTokenSource<TOptions>> _sources;

        public OptionsMonitor(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IOptionsChangeTokenSource<TOptions>> sources)
        {
            _sources = sources;
            _setups = setups;
            _optionsCache = new OptionsCache<TOptions>(setups);
        }

        public TOptions CurrentValue
        {
            get
            {
                return _optionsCache.Value;
            }
        }

        public IDisposable OnChange(Action<TOptions> listener)
        {
            var disposable = new ChangeTrackerDisposable();
            foreach (var source in _sources)
            {

                Action<object> callback = null;
                IDisposable previousSubscription = null;
                callback = (s) =>
                {
                    // The order here is important. We need to take the token and then apply our changes BEFORE
                    // registering. This prevents us from possible having two change updates to process concurrently.
                    //
                    // If the token changes after we take the token, then we'll process the update immediately upon
                    // registering the callback.
                    var token = source.GetChangeToken();

                    // Recompute the options before calling the watchers
                    _optionsCache = new OptionsCache<TOptions>(_setups);
                    listener(_optionsCache.Value);

                    // Remove the old callback after its been fired
                    var nextSubscription = token.RegisterChangeCallback(callback, s);
                    disposable.Disposables.Add(nextSubscription);
                    disposable.Disposables.Remove(previousSubscription);
                    previousSubscription = nextSubscription;
                };

                previousSubscription = source.GetChangeToken().RegisterChangeCallback(callback, state: null);
                disposable.Disposables.Add(previousSubscription);
            }
            return disposable;
        }
    }
OptionsMonitor

通過IOptionsChangeTokenSource的IChangeToken對象發出更改請求,之後Action<TOptions> listener進行數據更改。

Onchange方法,實現上就是每次調用都會創建一個新的IDisposable(ChangeTrackerDisposable),如此而已。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 問題描述 若一個數(首位不為零)從左向右讀與從右向左讀都一樣,我們就將其稱之為迴文數。 例如:給定一個10進位數56,將56加65(即把56從右向左讀),得到121是一個迴文數。 又如:對於10進位數87: STEP1:87+78 = 165 STEP2:165+561 = 726 STE...
  • Jdk:Java程式設計語言、Java虛擬機、Java API類庫。Jdk是用於支持Java程式開發的最小環境。Jre:Java API類庫中的Java SE API子集、Java虛擬機。Jre是支持Java程式運行的標準環境。Program Counter Register:較小的記憶體空間,可以看...
  • dt.ToString();//2005-11-5 13:47:04 dt.AddYears(1).ToString();//2006-11-5 13:47:04 dt.AddDays(1.1).ToString();//2005-11-6 16:11:04 dt.AddHours(1.1).ToS...
  • 2:Set集合(理解) (1)Set集合的特點 無序,唯一 (2)HashSet集合(掌握) A:底層數據結構是哈希表(是一個元素為鏈表的數組) B:哈希表底層依賴兩個方法:hashCode()和equals() 執行順序: 首先比較哈希值是否相同 相同:繼續執行equals()方法 返回true:...
  • 原文:http://www.cnblogs.com/FreeDong/archive/2013/07/31/3227638.html一、委托調用方式1. 最原始版本:delegate string PlusStringHandle(string x, string y);class Program{...
  • 首先是存儲過程,只取出我需要的那段數據,如果頁數超過數據總數,自動返回最後一頁的紀錄:set ANSI_NULLS ONset QUOTED_IDENTIFIER ONGO-- =============================================-- Author: Clear...
  • //c datetime 格式化DateTime dt = DateTime.Now;Label1.Text = dt.ToString();//2005-11-5 13:21:25Label2.Text = dt.ToFileTime().ToString();//1277564168599128...
  • 各位好,終於講到自定義Panel了。當系統自帶的幾個Panel比如Gird,StackPanel,RelativePanel不能滿足我們的特定要求時(其實不常見啦),自定義Panel就顯得非常必要,而且因為是針對性的處理,效果也會非常好。更何況自定義Panel其實並不複雜,今天俺們就來學習一下。.....
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...