使用Visual Studio Code開發Asp.Net Core WebApi學習筆記(七)-- 結構化配置


本篇將記錄.Net Core里頗有特色的結構化配置的使用方法。

相比較之前通過Web.Config或者App.Config配置文件里使用xml節點定義配置內容的方式,.Net Core在配置系統上發生了很大的變化,具有了配置源多樣化、更加輕量、擴展性更好的特點。

第一部分、基於鍵值對的配置

如果要使用結構化配置,需要先引用 "Microsoft.Extensions.Configuration": "1.0.0" nuget包。下面通過一個.Net Core控制台程序演示

一、單層結構的配置

 1 using Microsoft.Extensions.Configuration;
 2 using Microsoft.Extensions.Configuration.Memory;
 3 using System;
 4 using System.Collections.Generic;
 5 
 6 namespace DiApplicationTest
 7 {
 8     public class Program
 9     {
10         public static void Main(string[] args)
11         {
12             IDictionary<string, string> source = new Dictionary<string, string>()
13             {
14                 ["Ele1"] = "value1",
15                 ["Ele2"] = "value2"
16             };
17 
18             IConfiguration config = new ConfigurationBuilder().Add(new MemoryConfigurationSource() { InitialData = source }).Build();
19             Console.WriteLine($"Ele1: {config["Ele1"]}");
20             Console.WriteLine($"Ele2: {config["Ele2"]}");
21 
22             Console.ReadLine();
23         }
24     }
25 }

啟動調試,查看cmd窗口輸出內容

上面的例子里,將一個字典作為配置源讀入到config配置對象里,通過鍵可以讀取到對應的值。

二、多層結構的配置

在大多數情況下,項目里的配置都是多層結構的,也可以稱為是結構化的。在上面的例子的基礎上稍加修改,實現結構化的配置讀取。

 1 using Microsoft.Extensions.Configuration;
 2 using Microsoft.Extensions.Configuration.Memory;
 3 using System;
 4 using System.Collections.Generic;
 5 
 6 namespace DiApplicationTest
 7 {
 8     public class Program
 9     {
10         public static void Main(string[] args)
11         {
12             IDictionary<string, string> source = new Dictionary<string, string>()
13             {
14                 ["Ele1"] = "value1",
15                 ["Ele2:Sub1"] = "value2.1",
16                 ["Ele2:Sub2"] = "value2.2"
17             };
18 
19             IConfiguration config = new ConfigurationBuilder().Add(new MemoryConfigurationSource() { InitialData = source }).Build();
20             Console.WriteLine($"Ele1: {config["Ele1"]}");
21             Console.WriteLine($"Ele2.Sub1: {config.GetSection("Ele2")["Sub1"]}");
22             Console.WriteLine($"Ele2.Sub2: {config.GetSection("Ele2")["Sub2"]}");
23 
24             Console.ReadLine();
25         }
26     }
27 }

啟動調試,查看cmd窗口輸出內容

在這個例子里,字典內容描述了一個具有兩層結構的配置,第一層有Ele1和Ele2兩個節點,分別對應一個字符內容和一個復合內容,第二層有Sub1和Sub2兩個節點,同時掛在Ele2節點下,組成了一個復合結構。

注意看字典項里的Key,因為字典里的數據是扁平化的,為了能清晰描述節點之間的上下層關系,需要通過“:”符號來標識。

config對象通過GetSection方法來獲取當前節點的某個下級節點內容。

 

第二部分、其他配置來源

除了上面例子里展示的配置源來自內存內容,也可以來自Xml文件、JSON文件或者數據庫等。因為在.Net Core里使用JSON文件描述配置內容很常見,下面就展示如何讀取JSON配置文件。

先添加如下兩個nuget包,支持從json文件讀取內容

"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",

添加 appsettings.json 文件

1 {
2   "Ele1": "value1",
3   "Ele2": {
4     "Sub1": "value2.1",
5     "Sub2": "value2.2"
6   }
7 }

修改Main函數內容

 1 using Microsoft.Extensions.Configuration;
 2 using System;
 3 using System.IO;
 4 
 5 namespace DiApplicationTest
 6 {
 7     public class Program
 8     {
 9         public static void Main(string[] args)
10         {
11             IConfigurationBuilder builder = new ConfigurationBuilder();
12             builder.SetBasePath(Directory.GetCurrentDirectory());
13             builder.AddJsonFile("appsettings.json");
14 
15             IConfiguration config = builder.Build();
16             Console.WriteLine($"Ele1: {config["Ele1"]}");
17             Console.WriteLine($"Ele2.Sub1: {config.GetSection("Ele2")["Sub1"]}");
18             Console.WriteLine($"Ele2.Sub2: {config.GetSection("Ele2")["Sub2"]}");
19 
20             Console.ReadLine();
21         }
22     }
23 }

啟動調試,查看cmd窗口輸入內容,與上面的例子內容一致。

這個例子將原來在字典里的內容轉換成Json格式化的內容存儲在持久化文件里。通過指定配置源,同樣可以讀取內容。

 

第三部分、Options對象映射

當配置文件內容較多時,通過config的Key獲取對應的配置項的值變得比較繁瑣。.Net Core的配置系統采用了一種叫“Options Pattern”的模式使配置內容與有着對應結構的對象進行映射,這種對象就叫做Options對象。

下面將簡單演示一下這種映射方式。

首先添加如下nuget包引用,使用此模式的相關接口和類都在這個包里。同時還需要引入DI容器。

"Microsoft.Extensions.DependencyInjection": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",

添加兩個具有層級結構的Options類

 1     public class ConfigOptions
 2     {
 3         public string Ele1 { get; set; }
 4         public SubConfigOptions Ele2 { get; set; }
 5     }
 6 
 7     public class SubConfigOptions
 8     {
 9         public string Sub1 { get; set; }
10         public string Sub2 { get; set; }
11     }

修改Main函數內容

 1         public static void Main(string[] args)
 2         {
 3             // 創建DI容器,注冊Options Pattern服務
 4             IServiceCollection services = new ServiceCollection();
 5             services.AddOptions();
 6 
 7             // 讀取配置文件
 8             IConfigurationBuilder builder = new ConfigurationBuilder();
 9             builder.SetBasePath(Directory.GetCurrentDirectory());
10             builder.AddJsonFile("appsettings.json");
11             IConfiguration config = builder.Build();
12 
13             // 通過注冊的服務獲取最終映射的配置對象
14             IServiceProvider serviceProvider = services.Configure<ConfigOptions>(config).BuildServiceProvider();
15             ConfigOptions options = serviceProvider.GetService<IOptions<ConfigOptions>>().Value;
16 
17             Console.WriteLine($"Ele1: {options.Ele1}");
18             Console.WriteLine($"Ele2.Sub1: {options.Ele2.Sub1}");
19             Console.WriteLine($"Ele2.Sub2: {options.Ele2.Sub2}");
20 
21             Console.ReadLine();
22         }

啟動調試,查看cmd窗口輸入內容,與上面的例子內容一致。

在定義Options對象結構時,對象內的屬性名稱要與對應層級的配置Key的值保持一致,層級關系也要與配置內容的層級結構保持一致。

通過調用 services.AddOptions() 方法注冊Options Pattern服務。將配置內容注冊到容器里,來獲取對應的服務Provider對象。通過調用GetService方法獲得對應的真實服務對象,即帶有事先定義的Options類型的泛型接口IOptions,接口的Value值就是配置內容映射的Options對象。

 

第四部分、Asp.Net Core里的配置管理

這個系列之前使用的例子里添加配置管理相關的功能,來修改初始化日志級別的代碼,同時添加一些自定義配置。

先添加配置相關的nuget包

    "Microsoft.Extensions.Configuration": "1.0.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"

添加appsettings.json文件

 1 {
 2     // 日志配置
 3     "Logging": {
 4         "LogLevel": {
 5             "Microsoft": "Warning"
 6         }
 7     },
 8     // 自定義配置
 9     "CfgContent": {
10         "Ele1": "value1",
11         "Ele2": {
12             "Sub1": "value2.1",
13             "Sub2": "value2.2"
14         }
15     }
16 }

添加上個例子里的 ConfigOptions.cs、SubConfigOptions.cs 類,修改 Startup.cs 的內容,添加配置相關代碼

 1 using System.IO;
 2 using Microsoft.AspNetCore.Builder;
 3 using Microsoft.Extensions.Configuration;
 4 using Microsoft.Extensions.DependencyInjection;
 5 using Microsoft.Extensions.Logging;
 6 
 7 namespace WebApiFrame
 8 {
 9     public class Startup
10     {
11         public IConfiguration Configuration { get; }
12 
13         public Startup()
14         {
15             var builder = new ConfigurationBuilder()
16                 .SetBasePath(Directory.GetCurrentDirectory())
17                 .AddJsonFile("appsettings.json");
18 
19             Configuration = builder.Build();
20         }
21 
22         public void ConfigureServices(IServiceCollection services)
23         {
24             services.AddOptions();
25             services.Configure<ConfigOptions>(Configuration.GetSection("CfgContent"));
26 
27             // 注入MVC框架
28             services.AddMvc();
29         }
30 
31         public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
32         {
33             // 添加日志支持
34             loggerFactory.AddConsole(Configuration.GetSection("Logging"));
35             loggerFactory.AddDebug();
36 
37             // 添加NLog日志支持
38             //loggerFactory.AddNLog();
39 
40             // 添加MVC中間件
41             app.UseMvc();
42         }
43     }
44 }

修改 DemoController.cs 內容

 1 using System.Threading.Tasks;
 2 using Microsoft.AspNetCore.Http;
 3 using Microsoft.AspNetCore.Mvc;
 4 using Microsoft.Extensions.Options;
 5 
 6 namespace WebApiFrame
 7 {
 8     [Route("[controller]")]
 9     public class DemoController : Controller
10     {
11         private ConfigOptions _cfgContent { get; }
12 
13         public DemoController(IOptions<ConfigOptions> options)
14         {
15             _cfgContent = options.Value;
16         }
17 
18         [HttpGet("index")]
19         public async Task Index()
20         {
21             HttpContext.Response.ContentType = "text/html";
22             await HttpContext.Response.WriteAsync($"<span>Ele1: {_cfgContent.Ele1}</span><br />");
23             await HttpContext.Response.WriteAsync($"<span>Ele2.Sub1: {_cfgContent.Ele2.Sub1}</span><br />");
24             await HttpContext.Response.WriteAsync($"<span>Ele2.Sub2: {_cfgContent.Ele2.Sub2}</span><br />");
25         }
26     }
27 }

啟動調試,訪問地址 http://localhost:5000/demo/index ,頁面顯示配置內容

從這個例子里可以看到,讀取 appsettings.json 配置文件內容並分成兩部分,其中一部分配置Logging作為Logger的配置內容用於日志初始化,另外一部分CfgContent配置內容注冊到DI容器,在控制器的構造函數里通過IOptions泛型類型的參數注入,這樣控制器就可以讀取配置文件的內容。


免責聲明!

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



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