1. 程式人生 > >.NET Core 3.x之下的配置框架

.NET Core 3.x之下的配置框架

## 一.配置框架的核心類庫 首先我們使用.NET Core的配置框架需要安裝額外的NuGet擴充套件包,下面是列舉最常用的幾個擴充套件包以及所對應的配置功能 | NuGet Package | Description | | :------------------------------------------------------ | ------------------------------------------------------- | | Microsoft.Extensions.Configuration | 配置框架的核心庫,提供有關Configuration的抽象類和實現類 | | Microsoft.Extensions.Configuration.CommandLine | 能夠使用命令引數進行配置 | | Microsoft.Extensions.Configuration.EnvironmentVariables | 能夠使用環境變數進行配置 | | Microsoft.Extensions.Configuration.Json | 能夠使用json檔案進行配置 | | Microsoft.Extensions.Configuration.Xml | 能夠使用xml檔案進行配置 | | Microsoft.Extensions.Configuration.Ini | 能夠使用Ini檔案進行配置 | | Microsoft.Extensions.Configuration.Binder | 支援強型別物件繫結配置 | ## 二.一個Configuration的構建 下面我們在控制檯使用記憶體儲存配置資訊並且完成一個Configuration的構造,程式碼如下: ```C# static void Main(string[] args) { //定義一個ConfigurationBuilder IConfigurationBuilder builder = new ConfigurationBuilder(); //新增ConfigurationSource builder.AddInMemoryCollection(new Dictionary() { {"Name","Foo"}, {"Sex","Male" }, {"Job","Student" }, }); //通過Build構建出IConfiguration IConfiguration configuration = builder.Build(); foreach (var item in configuration.GetChildren()) { Console.WriteLine($"{item.Key}:{item.Value}"); } Console.ReadLine(); } ``` 輸出結果: ``` Job:Student Name:Foo Sex:Male ``` 那麼我們可以看到一個configuration的構建的步驟: - **定義ConfigurationBuilder** - **為ConfigurationBuilder新增ConfigurationSource** - **通過ConfigurationBuilder的Build方法完成構建** ## 三.通過命令列配置 首先我們在專案的除錯的應用程式引數加入命令列引數: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193439246-2006874934.png) 程式碼修改如下: ```c# builder.AddInMemoryCollection(new Dictionary() { {"Name","Foo"}, {"Sex","Male" }, {"Job","Student" }, }) .AddCommandLine(args); ``` 輸出: ``` Age:23 Job:Student Name:Ryzen Sex:Male ``` 同時我們在輸出結果看到,key為Name的value變化了,證明當不同配置源存在相同Key時,會被後新增的配置源覆蓋其value ## 四.通過環境變數配置 下面的環節由於出於演示效果,通過WPF程式來演示,首先建立好一個wpf專案,介面如下: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193716900-1925693133.png) 我們在專案的除錯的環境變數新增幾個引數: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193533730-43327867.png) 在App.cs中構建一個靜態屬性IConfiguration,程式碼如下: ```c# public partial class App : Application { public static IConfiguration MyConfigration => new ConfigurationBuilder() .AddEnvironmentVariables() } ``` MainWindow.cs: ```c# public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { LoadEnv(); } private void LoadEnv() { string envString = string.Empty; this.textbox_env.Text = $"Env__IsProduction:{App.MyConfigration.GetSection("Env")["IsProduction"]}"+"\n"; this.textbox_env.Text += $"Env__IsDevelopment:{App.MyConfigration.GetSection("Env")["IsDevelopment"] }"+"\n"; this.textbox_env.Text += $"Class__Team__Group:{App.MyConfigration.GetSection("Class:Team")["Group"]}"; } } ``` 實現效果: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193550463-939928341.gif) 在注入環境變數時,還支援去字首過濾篩選注入,修改App.cs: ``` public partial class App : Application { public static IConfiguration MyConfigration => new ConfigurationBuilder() .AddEnvironmentVariables("Env:") } ``` 修改MainWindow.cs: ```c# private void LoadEnv() { string envString = string.Empty; this.textbox_env.Text = $"Env__IsProduction:{App.MyConfigration.GetSection("Env")["IsProduction"]}"+"\n"; this.textbox_env.Text += $"Env__IsDevelopment:{App.MyConfigration.GetSection("Env")["IsDevelopment"] }"+"\n"; this.textbox_env.Text += $"Class__Team__Group:{App.MyConfigration.GetSection("Class:Team")["Group"]}" +"\n"; //過濾字首後 this.textbox_env.Text += $"IsProduction:{App.MyConfigration["IsProduction"]}"; } ``` 效果如下: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193600833-1121127301.gif) 我們會發現,之前的環境變數都被過濾了,只能讀取被過濾字首後的環境變數 **配置環境變數時的注意點:** - 和json等檔案不同,環境變數的Key是以__雙下劃線為分層鍵,而不是:冒號 - 分層讀取的時候是以冒號:來進行讀取 ## 五.通過檔案來配置 ### 1.建立和讀取配置檔案 首先我們新建一個Configurations資料夾,然後再該資料夾建立三個配置檔案 appsetting.json: ```json { "Human": { "Name": "Foo", "Body": { "Height": 190, "Weight": 170 }, "Sex": "Male", "Age": 24, "IsStudent": true } } ``` appsetting.xml: ```xml 12
11
``` appsetting.ini: ```ini [Ini] IniKey1=IniValue1 IniKey2=IniValue2 ``` 在App.cs分別注入這三個檔案: ```c# public partial class App : Application { public static IConfiguration MyConfigration => new ConfigurationBuilder() .AddEnvironmentVariables("Env:") .AddJsonFile(@"Configurations\appsetting.json", false, true) .AddXmlFile(@"Configurations\appsetting.xml", false, true) .AddIniFile(@"Configurations\appsetting.Ini") .Build(); } ``` 修改MainWindow程式碼,分別讀取這三個檔案: ```c# private void Button_Click(object sender, RoutedEventArgs e) { LoadEnv(); LoadJson(); LoadXML(); LoadIni(); } private void LoadJson() { var jsonString = string.Empty; foreach (var item in App.MyConfigration.GetSection("Human").GetChildren()) { if (item.Key.Contains("Body")) { foreach (var body in item.GetChildren()) { jsonString += $"{body.Key}:{body.Value} \n"; } } else { jsonString += $"{item.Key}:{item.Value} \n"; } } this.textbox_json.Text = jsonString; } private void LoadXML() { var xmlString = string.Empty; foreach (var item in App.MyConfigration.GetSection("DbServers").GetChildren()) { xmlString += $"{item.Key}:{item.Value} \n"; } this.textbox_xml.Text = xmlString; } private void LoadIni() { var iniString = string.Empty; foreach (var item in App.MyConfigration.GetSection("Ini").GetChildren()) { iniString += $"{item.Key}:{item.Value} \n"; } this.textbox_ini.Text = iniString; } ``` 效果如下: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193616494-999976128.gif) ## 2.支援檔案變更時重新讀取和設定變更監視 以json檔案為例,我們在App.cs注入json檔案時呼叫此方法 ```c# AddJsonFile(@"Configurations\appsetting.json", false, true) ``` 該方法有是一個過載方法,最常用的是三個引數的過載方法,下面是三個引數的作用 - **path**:檔案路徑 - **optional**:預設為false,當找不到該檔案路徑會報錯,true則不報錯 - **reloadOnChange**:預設為false,當為true時支援配置檔案變更後重新讀取 首先,我們為appsetting.json檔案設定屬性,複製到輸出目錄=>
如果較新則複製,生成操作=>內容 ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193629308-511858706.png) 然後我們通過一個內建的靜態方法監控檔案變更,修改MainWindows.cs: ```c# public MainWindow() { InitializeComponent(); ChangeToken.OnChange(() => App.MyConfigration.GetReloadToken(), () => { MessageBox.Show("檔案發生變更了"); }); } ``` 效果如下: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193639200-2102327608.gif) ## 六.強型別繫結配置 首先我們建立一個類用於繫結配置,程式碼如下: ```c# public class MyHumanConfig { public string Name { get; set; } public Body Body { get; set; } public string Sex { get; set; } public int Age { get; set; } public bool IsStudent { get; set; } } public class Body { public int Height { get; set; } public int Weight { get; set; } } ``` 在Mainwindow.cs新增以下程式碼: ```c# private void Button_Click(object sender, RoutedEventArgs e) { LoadEnv(); LoadJson(); LoadXML(); LoadIni(); LoadBind(); } private void LoadBind() { var bindString = string.Empty; MyHumanConfig config = new MyHumanConfig();//宣告變數 App.MyConfigration.GetSection("Human").Bind(config);//繫結變數 foreach (var configProperty in config.GetType().GetProperties()) { if (configProperty.PropertyType==typeof(Body)) { var body = configProperty.GetValue(config) as Body; foreach (var bodyProperty in body.GetType().GetProperties()) { bindString += $"{bodyProperty.Name}:{bodyProperty.GetValue(body)} \n"; } } else { bindString += $"{configProperty.Name}:{configProperty.GetValue(config)} \n"; } } this.textbox_bind.Text = bindString; } ``` 效果如下: ![](https://img2020.cnblogs.com/blog/1294271/202003/1294271-20200308193649501-10785076