1. 程式人生 > >.NET Core採用的全新配置系統[5]: 聊聊預設支援的各種配置源[記憶體變數,環境變數和命令列引數]

.NET Core採用的全新配置系統[5]: 聊聊預設支援的各種配置源[記憶體變數,環境變數和命令列引數]

較之傳統通過App.config和Web.config這兩個XML檔案承載的配置系統,.NET Core採用的這個全新的配置模型的最大一個優勢就是針對多種不同配置源的支援。我們可以將記憶體變數、命令列引數、環境變數和物理檔案作為原始配置資料的來源,如果採用物理檔案作為配置源,我們可以選擇不同的格式(比如XML、JSON和INI等) 。如果這些預設支援的配置源形式還不能滿足你的需求,我們還可以通過註冊自定義ConfigurationSource的方式將其他形式資料作為我們的配置來源。 [ 本文已經同步到《ASP.NET Core框架揭祕》之中]

目錄
一、記憶體變數
二、環境變數
三、命令列引數

一、記憶體變數

從本被系列第一篇開始到現在,我們所有的例項演示一直都在使用MemoryConfigurationSource這種型別的ConfigurationSource來提供原始的配置。我們知道MemoryConfigurationSource採用一個字典物件(具體來說應該是一個元素型別為KeyValuePair<string, string>的集合)作為存放原始配置資料的容器。作為一個ConfigurationSource,它總是通過建立某個對應的ConfigurationProvider來從事具體的配置資料讀取工作,那麼MemoryConfigurationSource會提供一個怎樣的ConfigurationProvider呢?

   1: public class MemoryConfigurationSource : IConfigurationSource
   2: {
   3:     public IEnumerable<KeyValuePair<string, string>> InitialData { get; set; }
   4:  
   5:     public IConfigurationProvider Build(IConfigurationBuilder builder)
   6:     {
   7:         return new MemoryConfigurationProvider(this
);
   8:     }
   9: }

上面給出的程式碼片段體現了MemoryConfigurationSource的完整定義,我們可以看到它具有一個IEnumerable<KeyValuePair<string, string>>型別的屬性InitialData來存放初始的配置資料。從Build方法的實現可以看出,真正被它用來讀取原始配置資料的是一個MemoryConfigurationProvider型別的物件,該型別的定義如下面的程式碼片段所示。

   1: public class MemoryConfigurationProvider : ConfigurationProvider, IEnumerable<KeyValuePair<string, string>>
   2: {
   3:     public MemoryConfigurationProvider(MemoryConfigurationSource source);
   4:     public void Add(string key, string value);
   5:     public IEnumerator<KeyValuePair<string, string>> GetEnumerator();
   6:     IEnumerator IEnumerable.GetEnumerator();
   7: }

從上面的程式碼片段可以看出,MemoryConfigurationProvider派生於抽象類ConfigurationProvider,同時還實現了IEnumerable<KeyValuePair<string, string>>介面。我們知道ConfigurationProvider直接使用一個Dictionary<string, string>來儲存配置資料,當我們根據一個MemoryConfigurationSource物件呼叫建構函式建立MemoryConfigurationProvider的時候,它只需要將通過InitiateData屬性儲存的配置資料轉移到這個字典中即可。MemoryConfigurationProvider還定義了一個Add方法是我們可以在任何時候都可以向配置字典中新增一個新的配置項。

通過前面對配置模型的介紹,我們知道ConfigurationProvider在配置模型中所起的作用就是讀取原始的配置資料並將其轉換成配置字典。在所有的預定義的ConfigurationProvider型別中,MemoryConfigurationProvider最為簡單直接,因為它對應的配置源就是一個配置字典,所以根本不需要作任何的結構轉換。

在利用MemoryConfigurationSource生成配置的時候,我們需要將它註冊到ConfigurationBuilder之上。具體來說,我們可以像前面演示的例項一樣直接呼叫ConfigurationBuilder的Add方法,也可以呼叫如下所示的了兩個過載的擴充套件方法AddInMemoryCollection。

   1: public static IConfigurationBuilder AddInMemoryCollection(this IConfigurationBuilder configurationBuilder);
   2: public static IConfigurationBuilder AddInMemoryCollection(this IConfigurationBuilder configurationBuilder, IEnumerable<KeyValuePair<string, string>> initialData);


二、環境變數

顧名思義,環境變數就是描述當前執行環境並影響程序執行行為的變數。按照作用域的不同,我們將環境變數劃分成三類,即分別針對當前系統、當前使用者和當前程序的環境變數。系統和使用者級別的環境變數儲存在登錄檔中,其路徑分別為“HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment”和“HKEY_CURRENT_USER\Environment ”。

環境變數提取和維護可以通過靜態型別Environment來實現。具體來說,我們可以呼叫它的靜態方法GetEnvironmentVariable方法獲得某個指定名稱的環境變數的值,而GetEnvironmentVariables方法則會將返回所有的環境變數,EnvironmentVariableTarget列舉型別的引數代表環境變數作用域決定的儲存位置。如果在呼叫GetEnvironmentVariable或者GetEnvironmentVariables方法師沒有顯式指定target引數或者將引數指定為EnvironmentVariableTarget.Process,在程序初始化前存在的所有環境變數(包括針對系統、當前使用者和當前程序)將會作為候選列表。

   1: public static class Environment
   2: {
   3:     public static string GetEnvironmentVariable(string variable);
   4:     public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target);
   5:  
   6:     public static IDictionary GetEnvironmentVariables();
   7:     public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target);
   8:  
   9:     public static void SetEnvironmentVariable(string variable, string value);
  10:     public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target);
  11: }
  12:  
  13: public enum EnvironmentVariableTarget
  14: {
  15:     Process,
  16:     User,
  17:     Machine
  18: }

環境變數的新增、修改和刪除均由SetEnvironmentVariable方法來完成,如果沒有顯式指定target引數,預設採用的是EnvironmentVariableTarget.Process。如果希望刪除指定名稱的環境變數,我們只需要在呼叫這個方法的時候將value引數設定為Null或者空字串即可。

除了在程式中利用靜態型別Environment,我們還可以執行命令列的方式檢視和設定環境變數。除此之外,我們還可以利用“系統屬性(System Properties)”設定工具以視覺化的方式檢視和設定系統和使用者級別的環境變數(“This PC”>“Properties”>“Change Settings”>“Advanced”>“Environment Variables”)。如果採用Visual Studio 2015來除錯我們編寫的應用,我們可以設定專案屬性的方式來設定程序級別的環境變數( “Properties” > “Debug”> “Environment Variables” )。

11

針對環境變數的配置源通過如下一個 EnvironmentVariablesConfigurationSource型別來表示,該型別定義在NuGet包“Microsoft.Extensions.Configuration.EnvironmentVariables”之中。該型別指定義了一個字串型別的屬性Prefix,它表示用於篩選環境變數採用的字首,也就是說如果我們設定了這個Prefix屬性,只會選擇名稱以此作為字首的環境變數。

   1: public class EnvironmentVariablesConfigurationSource : IConfigurationSource
   2: {
   3:     public string Prefix { get; set; }
   4:     public IConfigurationProvider Build(IConfigurationBuilder builder)
   5:     {
   6:         return new EnvironmentVariablesConfigurationProvider(this.Prefix);
   7:     }
   8: }

通過上面給出的程式碼片段我們可以看出EnvironmentVariablesConfigurationSource會利用對應的EnvironmentVariablesConfigurationProvider來完成對環境變數的讀取工作。如下所示的程式碼基本體現了EnvironmentVariablesConfigurationProvider的定義。由於作為原始配置資料的環境變數本身就是一個Key和Value均為字串的資料字典,所以EnvironmentVariablesConfigurationProvider無需在進行結構轉換,所以當Load方法被執行之後,它只需要將符合條件篩選出來並新增到自己的配置字典中即可。值得一提的是,如果我們在建立EnvironmentVariablesConfigurationProvider物件是指定了用於篩選環境變數的字首,當符合條件的環境變數被新增到自身的配置字典之後,這個字首也會從元素的Key中剔除。這個細節也體現在上面定義的Load方法中。

   1: public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider
   2: {
   3:     private readonly string prefix;
   4:  
   5:     public EnvironmentVariablesConfigurationProvider(string prefix = null)
   6:     {
   7:         this.prefix = prefix ?? string.Empty;
   8:     }
   9:  
  10:     public override void Load()
  11:     {
  12:         var dictionary = Environment.GetEnvironmentVariables()
  13:             .Cast<DictionaryEntry>()
  14:             .Where(it => it.Key.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
  15:             .ToDictionary(it => it.Key.ToString().Substring(prefix.Length), it => it.Value.ToString());
  16:         this.Data = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
  17:     }
  18: }

在使用EnvironmentVariablesConfigurationSource的時候,我們可以呼叫Add方法將它註冊到指定的ConfigurationBuilder物件上。除此之外,EnvironmentVariablesConfigurationSource的中註冊還可以直接呼叫IConfigurationBuilder介面的如下兩個過載的擴充套件方法AddEnvironmentVariables來完成。

   1: public static IConfigurationBuilder AddEnvironmentVariables(this IConfigurationBuilder configurationBuilder);
   2: public static IConfigurationBuilder AddEnvironmentVariables(this IConfigurationBuilder configurationBuilder, string prefix);

我們照例編寫一個簡單的例項來演示如何採用環境變數作為配置源。如下面的程式碼片段所示,我們呼叫Environment的靜態方法SetEnvironment方法設定了四個環境變數,變數名稱具有相同的字首“TEST_”。我們呼叫方法AddEnvironmentVariables建立一個EnvironmentVariablesConfigurationSource物件並將其註冊到建立的ConfigurationBuilder之上。呼叫AddEnvironmentVariables方法是我們將環境變數名稱字首“TEST_” 作為引數。後續的程式碼我們已經很熟悉了,即採用Options模式讀取環境變數並繫結為一個Profile物件。

   1: Environment.SetEnvironmentVariable("TEST_gender", "Male");
   2: Environment.SetEnvironmentVariable("TEST_age", "18");
   3: Environment.SetEnvironmentVariable("TEST_contactInfo:emailAddress", "[email protected]");
   4: Environment.SetEnvironmentVariable("TEST_contactInfo:PhoneNo", "123456789");
   5:  
   6: IConfiguration config = new ConfigurationBuilder()
   7:     .AddEnvironmentVariables("TEST_")
   8:     .Build();
   9:  
  10: Profile profile = new ServiceCollection()
  11:     .AddOptions()
  12:     .Configure<Profile>(config)
  13:     .BuildServiceProvider()
  14:     .GetService<IOptions<Profile>>()
  15:     .Value;


三、命令列引數

在很多情況下,我們會採用Self-Host的方式將一個ASP.NET Core應用寄宿一個託管程序中,在這種情況下我們傾向於採用命令列的方式來啟動寄宿程式。當以命令列的形式啟動一個ASP.NET Core應用時,我們希望直接使用命名行開關(Switch)來控制應用的一些行為,所以命令列開關自然也就成為了配置常用的來源之一。配置模型針對這種配置源的支援是通過CommandLineConfigurationSource來實現的,該型別定義在NuGet包 “Microsoft.Extensions.Configuration.CommandLine”中。

在以命令列的形式執行某個命令的時候,命令列開關(包括名稱和值)體現為一個簡單的字串集合,所以CommandLineConfigurationSource的根本目的在於將命名行開關從字串陣列轉換成配置字典。要充分理解這個轉換規則,我們先得來了解一下CommandLineConfigurationSource支援的命令列開關究竟採用怎樣的形式來指定。我們通過一個簡單的例項來說明命令列開關的集中指定方式。假設我們有一個命令“exec”並採用如下所示的方式執行某個託管程式(app)。

   1: exec app {options} 

在執行這個命令的時候我們通過相應的命令列開關指定兩個選項,其中一個表示採用的CPU架構(X86或者X64),另一個表示執行時型別(CLR或者CoreCLR),我們將這兩個命令列開關分別命名為architecture和runtime。在執行命名行的時候,我們可以採用如下三種不同的方式指定這兩個命名行開關。

   1: exec app /architecture x64 /runtime coreclr
   2: exec app --architecture x64 --runtime coreclr
   3: exec app architecture=x64 architecture=coreclr

為了執行上的便利,很多命名行開關都具有縮寫的形式,命令列開關的全名和縮寫之間具有一個對映關係(Switch Mapping)。以上述的這兩個命令列開關為例,我們可以採用首字母“a”和“r”來代表作為全名的“architecture”和“runtime”。如果採用縮寫的命令列開關名稱,那麼我們就可以按照如下兩種方式指定CPU架構和執行時型別。

   1: exec app –-a x64 –-r coreclr
   2: exec app -a x64 -r coreclr

綜上所示,我們一共有五種指定命名行開關的方式,其中三種採用命令列開關的全名,餘下的兩種則使用命令列開關的縮寫形式。下表總結了這五種命名開關的指定形式所採用的原始引數以及縮寫與全名的對映關係。這裡隱藏著一個重要的細節,字元 “-” 只能以縮寫的形式指定命令列開關的指,但是 “--” 則支援全稱和縮寫形式。

Arguments

Switch Mapping

/architecture x64 /runtime coreclr

-

--architecture x64 --runtime coreclr

-

architecture=x64 runtime=coreclr

-

--a x64 --r coreclr

--a: architecture, --r: runtime

-a x64 -r coreclr

-a: architecture, -r: runtime

原始的命令列引數總是體現為一個字串陣列, CommandLineConfigurationSource以字串陣列作為配置源,並利用對應的ConfigurationProvider將它轉換成配置字典。如下面的程式碼片斷所示,CommandLineConfigurationSource具有Args和SwitchMappings,前者正式代表承載著原始命令列引數的字串陣列,後者則儲存了命令列開關的縮寫與全稱之間的對映關係。在實現的Build方法中,它根據這兩個屬性創建出一個CommandLineConfigurationProvider物件。

   1: public class CommandLineConfigurationSource : IConfigurationSource
   2: {
   3:     public IEnumerable<string>         Args { get; set; }
            
           

相關推薦

.NET Core採用全新配置系統[5]: 聊聊預設支援各種配置[記憶體變數,環境變數命令引數]

較之傳統通過App.config和Web.config這兩個XML檔案承載的配置系統,.NET Core採用的這個全新的配置模型的最大一個優勢就是針對多種不同配置源的支援。我們可以將記憶體變數、命令列引數、環境變數和物理檔案作為原始配置資料的來源,如果採用物理檔案作為配置源,我們可以選擇不同的格式(比如XML

.NET Core採用全新配置系統[7]: 將配置儲存在資料庫中

我們在《聊聊預設支援的各種配置源》和《深入瞭解三種針對檔案(JSON、XML與INI)的配置源》對配置模型中預設提供的各種ConfigurationSource進行了深入詳盡的介紹,如果它們依然不能滿足專案中的配置需求,我們可以還可以通過自定義ConfigurationProvider來支援我們希望的配置來源

.NET Core採用全新配置系統[4]: “Options模式”下各種型別的Options物件是如何繫結的?

旨在生成Options物件的配置繫結實現在IConfiguration介面的擴充套件方法Bind上。配置繫結的目標型別可以是一個簡單的基元型別,也可以是一個自定義資料型別,還可以是一個陣列、集合或者字典型別。通過前面的介紹我們知道ConfigurationProvider將原始的配置資料讀取出來後會將其轉成K

.NET Core採用全新配置系統[2]: 配置模型設計詳解

在《.NET Core採用的全新配置系統[1]: 讀取配置資料》中,我們通過例項的方式演示了幾種典型的配置讀取方式,其主要目的在於使讀者朋友們從程式設計的角度對.NET Core的這個全新的配置系統具有一個大體上的認識,接下來我們從設計的維度來重寫認識它。通過上面演示的例項我們知道,配置的程式設計模型涉及到三

.NET Core採用全新配置系統[8]: 如何實現配置與原始檔的同步

配置的同步涉及到兩個方面:第一,對原始的配置檔案實施監控並在其發生變化之後從新載入配置;第二,配置重新載入之後及時通知應用程式進而使後者能夠使用最新的配置。接下來我們利用一個簡單的.NET Core控制檯應用來演示針對檔案的配置會涉及到資料同步的問題,我們希望應用能夠對原始配置檔案實施監控,並在檔案內容發生改

.NET Core採用全新配置系統[6]: 深入瞭解三種針對檔案(JSON、XML與INI)的配置

物理檔案是我們最常用到的原始配置的載體,最佳的配置檔案格式主要由三種,它們分別是JSON、XML和INI,對應的配置源型別分別是JsonConfigurationSource、XmlConfigurationSource和IniConfigurationSource。 [ 本文已經同步到《ASP.NET Co

.NET Core採用全新配置系統[9]: 為什麼針對XML的支援不夠好?如何改進?

物理檔案是我們最常用到的原始配置的載體,最佳的配置檔案格式主要由三種,它們分別是JSON、XML和INI,對應的配置源型別分別是JsonConfigurationSource、XmlConfigurationSource和IniConfigurationSource。但是對於.NET Core的配置系統來說,

.NET Core採用全新配置系統[1]: 讀取配置資料

提到“配置”二字,我想絕大部分.NET開發人員腦海中會立馬浮現出兩個特殊檔案的身影,那就是我們再熟悉不過的app.config和web.config,多年以來我們已經習慣了將結構化的配置定義在這兩個檔案之中。到了.NET Core的時代,很多我們習以為常的東西都發生了改變,其中也包括定義配置的方式。總的來說,

.NET Core採用全新配置系統[10]: 配置的同步機制是如何實現的?

配置的同步涉及到兩個方面:第一,對原始的配置檔案實施監控並在其發生變化之後從新載入配置;第二,配置重新載入之後及時通知應用程式進而使後者能夠使用最新的配置。要了解配置同步機制的實現原理,先得從認識一個名為ConfigurationReloadToken的型別開始。 [ 本文已經同步到《ASP.NET Core

.NET Core採用全新配置系統[3]: “Options模式”下的配置是如何繫結為Options物件

配置的原子結構就是單純的鍵值對,並且鍵和值都是字串,但是在真正的專案開發中我們一般不會單純地以鍵值對的形式來使用配置。值得推薦的做法就是採用《.NET Core採用的全新配置系統[1]: 讀取配置資料》最後演示的方式將相關的配置定義成一個Options型別,並採用與型別定義想匹配的結構來定義原始的配置,這樣就

.net core學習筆記《新一代的配置系統Configuration在支持多數據,熱更新,層級化方面代碼快速實踐》

配置文件 stat variables ack lec 復制 image onf sof 在我們之前.Net Framework的項目中,配置文件是WebConfig或AppcConfig文件,而當我們想要添加我們自定義的節點時,還需要在這個文件中的section中定義我們

部署Asp.net Core 項目發生502.5 或者500 沒有其他提示信息

pat res log led rac utl 導致 con ilog 最近將公司原來.NetCore 1.6的項目升級到.net Core 2.0首先發生 502.5的錯誤,包括IIS日誌,Windows應用程序日誌都沒有記錄問題始終解決不了,首先看看官網給出

Asp.Net Core 2.0 項目實戰(6)Redis配置、封裝幫助類RedisHelper及使用實例

命名 redis數據庫 remove per chang open htm lazy 鏈接 本文目錄 1. 摘要 2. Redis配置 3. RedisHelper 4.使用實例 5. 總結 1. 摘要   由於內存存取速度遠高於磁盤讀取的特

.net core出現Http Error 502.5 - Process Failure

nbsp code strip 分享 下載 錯誤 2-2 www. out 這個一般是本地的.NET Core SDK版本不統一報錯造成的。解決思路首先你要去找你的IIS報錯日誌,得到的錯誤代碼 ErrorCode = '0x80004005 : 8000808c.

Asp.net Core MVC 項目系統搭建與應用

開始 min 項目 pin mysql 高級 work ddd nbsp 第一部分 編程基礎 Asp.net Core 簡介 Asp.net Core 開始 Asp.net Core MVC 簡介 第二部分 基礎框架 Asp

.net core 部署在Linux系統上執行的環境搭建總結

原文: .net core 部署在Linux系統上執行的環境搭建總結   安裝Linux用的是騰訊雲的centos7.5,需要安裝有環境有mysql5.7  .netcore2.1 nginx1.14 1.首先是mysql的安裝 我用的連結工具是putty,首先root登入系統

.NET Core SDK在Windows系統安裝後出現Failed to load the hostfxr.dll等問題的解決方法

這次無論如何也要記錄下,原因是今天在一臺Windows2008R2的電腦上安裝.NET Core SDK後再命令列執行dotnet --info 居然爆出了“Failed to load the hostfxr.dll”的問題,之前也遇到過,但是解決了,卻沒有做記錄,害的這裡又google了一把!所以寫篇文章

基於.net core webapi的日誌系統——介面實現

開發環境vs2017,資料寫入到mongodb。思路就是1.提供介面寫入日誌,2.基於介面封裝類庫。 1.為什麼要寫它 很多開源專案像nlog、log4net、elk、exceptionless等都挺好的。就是除了引入所需類庫,還要在專案中新增配置,不喜歡。elk在分散式海量資料收集和檢索方面可能更能發揮它的

使用.NET Core 2開發部署Angular 5專案

目錄 介紹 背景 先決條件 開發設定 Angular 5設定 調整 部署的最後步驟 在Visual Studio 2017中使用.NET Core 2設定Angular 5以進行開發和部署的步驟。 介紹 在使用Visual Studio 2017建立和

ASP.net Core IIS釋出報502.5錯誤

一、執行環境 伺服器的系統是64位Windows Server 2012,ASP.net Core程式是一個MVC的小應用,選擇的是獨立釋出,目標系統是Win81 x64。 二、錯誤原因 把釋出的一堆東西拷到伺服器之後開啟IIS管理,確認已經安裝了aspnetc