.NET Core 3.0之深入源码理解Configuration(一)
微軟在.NET Core里設計出了全新的配置體系,并以非常靈活、可擴展的方式實現。從其源碼來看,其運行機制大致是,根據其Source,創建一個Builder實例,并會向其添加Provider,在我們使用配置信息的時候,會從內存中獲取相應的Provider實例。
.NET Core采用了統一的調用方式來加載不同類型的配置信息,并通過統一的抽象接口IConfigurationSource對配置源進行管理,這也是剛剛所說的靈活。而其擴展性就是我們可以自己自定義新的Provider實例,而不會改變其原來的調用方式。接下來的文章將會基于Consul,擴展一個新的Provider實例。
在ASP.NET Core 中,我們的應用配置是基于IConfigurationProvider的鍵值對。 我們先看一下思維導圖:
基于上圖,我們可以看到主要有鍵值對源有多種,分別是:
?環境變量
命令行參數
各種形式的配置文件
內存對象
用戶自定義擴展源?
在介紹.NET Core配置功能之前,先簡要說明一下Microsoft.Extensions.Configuration.Abstractions,該組件抽象了.NET Core的配置功能,并對自定義擴展制定了新的標準。以下介紹的四個核心對象全部來自于該組件。
IConfiguration
該接口表示一組鍵/值應用程序配置屬性,應用程序使用配置時的入口對象,.NET Core對其有多種擴展,其派生類包括位于統一類庫的IConfigurationSection,以及Microsoft.Extensions.Configuration類庫中的ConfigurationRoot、ConfigurationSection、IConfigurationRoot。我們可以通過DI獲取IConfiguration實例。
它主要有以下三個方法:
GetChildren():獲取直接子配置子節
GetReloadToken():返回一個IChangeToken,可用于確定何時重新加載配置
GetSection(String):獲取指定鍵的子節點
我們來看一下源碼:
通常我們要求配置文件要有足夠的靈活性,尤其是我們所擴展的配置信息存放在了其他服務器,當修改的時候我們很需要一套監控功能,以及時靈活的應對配置信息的修改?,F在.NET Core為我們提供了這樣一個功能,我們只需要自定義少量代碼即可完成配置信息的同步。這個方法就是GetReloadToken(),其返回值是IChangeToken。此處對配置信息的同步只做一個引子,后面的文章會詳細說明。
由于ConfigurationRoot、ConfigurationSection聚集于IConfiguration接口,此處也對這兩個類進行討論,方便我們對.NET Core的配置功能有個更加形象的印象。這兩個接口,本質上就是.NET Core關于配置信息的讀取方式。
XML是使用比較廣泛的一種數據結構,我們在配置XML時,一般會使用根節點、父節點、子節點之類的術語,此處也一樣。
ConfigurationRoot是配置的根節點,也實現了IConfigurationRoot,此接口只有一個方法,其主要功能就是實現對配置信息的重新加載,另外還包括一個IConfigurationProvider類型的集合屬性。其源碼如下
通過源碼我們知道,如果調用了Reload()方法,所有類型的Provider都會重新加載。
前面有ConfigurationRoot表示配置的根節點,那么ConfigurationSection則表示非跟節點,畢竟父節點、子節點都是相對,所以此處使用非根節點。ConfigurationSection繼承于IConfigurationSection,該接口只有三個只讀屬性,分別表示配置信息的Key、Value以及路徑信息,需要指出的是,此處的路徑信息主要指從根節點到當前節點的路徑,以表示當前節點的位置,類似于A:B:C可以表示節點C的位置,其中A、B、C都是ConfigurationSection的Key。以下是ConfigurationSection的源碼
IConfigurationBuilder
該接口主要用于創建IConfigurationProvider,其派生類包括Microsoft.Extensions.Configuration.ConfigurationBuilder。其成員包括
兩個只讀屬性:
Properties:獲取可用于在IConfigurationBuilder之間共享數據的鍵/值集合
Sources:該屬性用于緩存不同的配置源,以用于相對應的Provider的創建
兩個方法:
Add(IConfigurationSource source):新增IConfigurationSource,并添加到屬性中Sources中
Build():該方法遍歷Sources屬性,并調用IConfigurationSource的Build()方法,通過獲取Provider集合,最終創建IConfigurationRoot對象
ConfigurationBuilder源碼如下
此處令人感慨頗多,我們最終調用 ConfigurationRoot 的構造函數,究其原因是Provider提供了統一的數據訪問方式,不管是基于何種類型的Provider,我們都可以調用其Load()方法加載配置項。此外,IConfigurationBuilder本身有很多的擴展方法來注冊數據源,比如AddJsonFile()擴展方法。我們來看一下,我們常見的寫法,
IConfigurationSource
該接口表示應用程序配置的鍵值對。其派生類包括Microsoft.Extensions.Configuration.ChainedConfigurationSource、Microsoft.Extensions.Configuration.Memory.MemoryConfigurationSource。另外該派生類還會在文件類配置場景下依賴Microsoft.Extensions.Configuration.FileExtensions組件。
它是所有配置源的抽象表示,包括JSON、XML、INI、環境變量等等。通過上文我們也知道了,IConfigurationBuilder會注冊多個IConfigurationSource實例。它只有一個方法,就是Build()方法,并返回IConfigurationProvider,由此可見,IConfigurationProvider的創建依賴于IConfigurationSource,這也是一一對應的關系。所有不同的源最終都會轉化成統一的鍵值對表示。
以下是MemoryConfigurationSource的源碼
IConfigurationProvider
通過上文的介紹,我們可以知道IConfigurationProvider是統一的對外接口,對用戶提供配置的查詢、重新加載等功能。其派生類包括Microsoft.Extensions.Configuration.ConfigurationProvider、Microsoft.Extensions.Configuration.ChainedConfigurationProvider、Microsoft.Extensions.Configuration.Memory.MemoryConfigurationProvider。另外該派生類還會在文件類配置場景下依賴Microsoft.Extensions.Configuration.FileExtensions組件。
以下是Microsoft.Extensions.Configuration.ConfigurationProvider的源碼:
通過源碼,我們可以知道ConfigurationProvider以字典類型緩存了多個Provider對象,有需要的時候,從內存中獲取即可,配置的加載通過Load()方法實現,在ConfigurationRoot里我們介紹了其Reload,并且說明其方法是在循環調用ConfigurationProvider的Load方法,但是此處只提供了一個虛方法,其目的是要交給其他具體的Provider,比如環境變量、JSON、XML等,這些具體的Provider可以從相應的配置源中獲取配置信息。所有的子節點KEY通過GetChildKeys方法實現,其重新加載方式通過ConfigurationReloadToken實例完成。
另外需要說明一下,在ConfigurationProvider構造函數里,對字典進行了初始化,并同時設置了字典Key不受大小寫限制,這是一個需要注意的細節。
通過查看.NET配置功能的源碼,所有依賴均基于Microsoft.Extensions.Configuration.Abstractions,在其上有一層實現,即Microsoft.Extensions.Configuration,其內部也多數是抽象實現,并提供了多個虛方法交給其派生組件,比如環境變量、命令行參數、各種文件型配置等,當然各種文件型配置還要依賴Microsoft.Extensions.Configuration.FileExtensions組件。
以下是.NET Core 3.0預覽版里的Configuration各個組件的結構圖:
原文地址:https://www.cnblogs.com/edison0621/p/10854215.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的.NET Core 3.0之深入源码理解Configuration(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .net core编写转发服务
- 下一篇: 给 asp.net core 写一个简单