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

来源:http://www.cnblogs.com/artech/archive/2016/08/03/new-config-system-05.html
-Advertisement-
Play Games

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


較之傳統通過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
	   

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

-Advertisement-
Play Games
更多相關文章
  • 今天編碼時遇到了一個問題,大致描述就是去讀取excel中的某列,如圖: 這些是文件名,類似一個對應關係表,然後代碼去查找對應的文件。 斷點調試出來的內容也是正常,但是都匹配不到(文件真實存在),在打出log時發現了端倪: 有些空格變成了問號。難道是我的打開方式不對麽。。。? 嘗試了幾種不同編碼打開, ...
  • 一、 通過AccountManagement 程式集(System.DirectoryServices.AccountManagement) acountManagement 包含有: 1. UserPrincipals 2. GroupPrincipal 3.ComputerPrincipals ...
  • 最近學習xamarin。剛好 手上有一個lumia 930.所以試一試把uwp app部署到手機上,並真機調試一把。 目前環境: 1.開發pc電腦是win10,版本1607.加入了insider,所以版本比較高。 2.手機是 lumia 930.版本 1511,手機未加入insider,所以是穩定版 ...
  • 放暑假了,生活基本穩定下來,項目的剩餘部分也要開始慢慢的研究了。 項目GitHub地址: https://github.com/Andyahui/xgyxsh_WeiXin SDK的GitHub地址:https://github.com/JeffreySu/WeiXinMPSDK/ SDK官方介紹博 ...
  • 一、前言 可能項目規模較小,項目中除了增刪改查就只剩下業務流程,以前都沒怎麼弄明白的東西時間長了就越發的模糊了... 二、使用場景 MSDN:delegate 是一種可用於封裝命名或匿名方法的引用類型。 委托類似於 C++ 中的函數指針;但是,委托是類型安全和可靠的。 BeginInvoke 方法啟 ...
  • 1. 使用場景 來著stackorverflow controls concurrent access to a shared resource. access to the resource will be requested from multiple, disparate parts of t ...
  • 適用於: 本文適用於有一定微信開發基礎的用戶 引言: 花了300大洋申請了微信公眾平臺後,發現不能使用微信公眾號登錄網站(非微信打開)獲得微信帳號。仔細研究後才發現還要再花300大洋申請微信開放平臺才能接入網站的登錄。於是做為屌絲程式員的我想到了自己做一個登錄介面。 工具和環境: 1. VS2013 ...
  • 策略一:資料庫不存在時重新創建資料庫 Database.SetInitializer<testContext>(new CreateDatabaseIfNotExists<testContext>()); Database.SetInitializer<testContext>(new Create ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...