.Net Core中的配置文件源碼解析


一、配置簡述

  之前在.Net Framework平台開發時,一般配置文件都是xml格式的Web.config,而需要配置其他格式的文件就需要自己去讀取內容,加載配置了。.而Net Core支持從命令行、環境變量、文件、內存、Key-per-file中加載配置,其中文件包括xml、ini、json三種文件格式。這里需要說明一下,不論哪種格式的配置文件,加載到程序中最終會以Key/Value形式保存,源碼中將所有配置讀取出來並保存在  Dictionary<string, string> Data  的字典中。額外說明一下Key-per-file配置方式是以文件名稱為key,文件內容為value的形式。

二、源碼解析

  點擊查看源碼,我畫了一個主要類之間的邏輯關系圖,如下:

實線表示繼承關系,每條虛線表示意義已經在上面表明。可以分為4個部分,最終要構建的就是IConfigurationRoot,因為所有的配置都存儲在它里面的Providers集合中的Data的字典中。

構建它兩條路徑,一條通過IConfigurationSource構建IConfigurationProvider,然后通過IConfigurationProvider集合構建IConfigurationRoot,也就是圖上標記的1/2兩步。

另一條是通過IConfigurationSource集合構建IConfigurationBuilder,在通過Builder方法遍歷循環創建創建IConfigurationProvider集合,在通過IConfigurationProvider集合構建IConfigurationRoot。也就是圖上的3/4兩步。這里只講文件配置方式,包括xml、ini、json文件。

IConfigurationSource:

  它是配置文件的根本,它表示配置文件本身,比如繼承自它的 FileConfigurationSource 里面有個Path屬性,表示文件路徑,會通過這個Path讀取這個文件內容。如我們常用的xml、json、ini文件配置都繼承自  FileConfigurationSource 。 

IConfigurationProvider:

  前面說了,配置最終會轉換為key/value的形式,而 IConfigurationProvider 就是這個裝換。比如繼承他的 FileConfigurationProvider ,它的構造函數需要傳第一個  FileConfigurationSource   ,  FileConfigurationProvider   會根據  FileConfigurationSource   的 path 屬性找到對應文件,然后讀取配置文件到它的  IDictionary<string, string> Data  中。xml的讀取在  XmlConfigurationProvider  中,json文件的讀取在  JsonConfigurationProvider  。

        private void Load(bool reload)
        {
            //刪除一些判斷邏輯
            if (reload) { Data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } using (var stream = file.CreateReadStream()) {           //這一步會將文件里面的配置 放到Data中 不同的文件格式Load方法都有對應的實現,這里就不細看了。 Load(stream); }  OnReload(); } 

  一個 IConfigurationProvider 的實現類中會包含一個對應的  IConfigurationSource  的實現類,比如  JsonConfigurationProvider  類中包含一個 JsonConfigurationProvider  

IConfigurationRoot:

  所有的類最終構建的目標就是IConfigurationRoot,它包含一個 IList<IConfigurationProvider> _providers 集合,而每一個  IConfigurationProvider  包含一個  IDictionary<string, string> Data  ,所以現在你現在是不是有提花灌頂的感覺。這樣做的目的是一個程序可能有多個配置文件,可能有一個xml文件、一個json文件、一個Ini文件。每個配置文件會被讀取到對應的  ConfigurationSource  中,然后通過它構建對應的  ConfigurationProvider  ,然后用三個  ConfigurationProvider  構建  ConfigurationRoot  。

那這樣會有一個問題,比如xml文件配置了 A的值為1,json文件也配置名稱為A的值為2,那會獲取誰的值呢? 下面源碼可以看到,IConfigurationRoot會反轉添加的順序,循環遍歷,如果找到就返回,所以后面添加的會覆蓋前面添加的。

        public string this[string key]
        {
            get {  //_providers也就是IConfigurationRoot里面的IList<IConfigurationProvider> foreach (var provider in _providers.Reverse()) { string value; if (provider.TryGet(key, out value)) { return value; } } return null; } set { if (!_providers.Any()) { throw new InvalidOperationException(Resources.Error_NoSources); } foreach (var provider in _providers) { provider.Set(key, value); } } }

 對於Json、xml、ini文件,比如

{
  "user": { "address": { "Provice": "浙江省", "city": "杭州市" }, "name": "張三" } }

在Data中存儲的key為 user:address:Province、user:address:city和user:name。中間以“:”分割,這個“:”是固定只讀的,不可以改變的。

三、簡單使用

  創建一個WebApi項目,修改Program代碼如下:

        public static void Main(string[] args)
        {
            var configRoot = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory())//設置基礎路徑 .AddJsonFile("a.json")//加載配置 .AddXmlFile("b.xml") .Build(); var builder = new WebHostBuilder() .UseConfiguration(configRoot) .UseContentRoot(Directory.GetCurrentDirectory()) .UseKestrel() .UseStartup<Startup>() .Build(); builder.Run(); }

  然后當用的時候,只需要注入 IConfiguration ,就能獲取所有的配置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM