簡讀《ASP.NET Core技術內幕與項目實戰》之3:配置
- 2022 年 10 月 22 日
- 筆記
- 配置, aspnetcore, AspNetCore/ABP/MASA/Harmony
特別說明:
1、本系列內容主要基於楊中科老師的書籍《ASP.NET Core技術內幕與項目實戰》及配套的B站影片影片教程,同時會增加極少部分的小知識點
2、本系列教程主要目的是提煉知識點,追求快准狠,以求快速複習,如果說書籍學習的效率是影片的2倍,那麼「簡讀系列」應該做到再快3-5倍
本節內容,涉及3.2(P60-P69),7.2(P188-P193),NuGet包
- Microsoft.Extensions.Configuration
- Microsoft.Extensions.Configuration.Json
- Microsoft.Extensions.Configuration.CommandLine
- Microsoft.Extensions.Configuration.EnvironmentVariables
- Microsoft.Extensions.Configuration.Binder
- Microsoft.Extensions.Options
- ...
一、直接讀取配置
1 //appsetting.json文件,需設置為「如果較新則複製」 2 { 3 "name": "functionMC", 4 "proxy": { 5 "address": "192.1.1.1", 6 "port": 1088 7 } 8 } 9 10 11 //Program.cs 12 ConfigurationBuilder configBuilder = new ConfigurationBuilder(); 13 configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange:false); 14 IConfigurationRoot config = configBuilder.Build(); 15 16 string name = config["proxy:address"]; 17 Console.WriteLine(name); 18 19 string proxyAddress = config.GetSection("name").Value; 20 Console.WriteLine(proxyAddress);
程式碼解釋:
12-13行:構建ConfigurationBuild對象,並調用該對象的AddJsonFile方法,載入Json配置文件
14行:調用ConfigurationBuild對象的Build方法,構建IConfigurationRoot對象-config,用於讀取配置
16行:通過config["key"]方式,讀取key值,讀取聯級key的方式,與config.GetSection一致,"proxy:address"
19行:通過config.GetSection方法,讀取key值
補充說明:
①涉及類型: ConfigurationBuild(配置)、IConfigurationRoot(讀取)-體現面向介面編程,根據不同的配置源有不同的實現
②13行可以設置其它配置源:
- 從命令行讀取:configBuild.AddCommandLine(args);
- 從環境變數讀取:configBuild.AddEnvironmentVariables("Test_"),其中Test_為環境變數的前綴,可以實現過濾
- 其它配置源:INI文件、XML文件、Key-per-file文件、用戶機密、第三方配置提供程式等
- 當在13行,配置多個數據源時,按Add的添加順序讀取,如果多個配置源設置了相同的key,則後面的key值覆蓋前面的key值
- 在ASP.NET Core,已經默認添加了多個配置源,添加順序為appsettings.json < appsettings.[運行時環境變數].json< 用戶機密 < 環境變數 < 命令行
③在VS上設置命令行參數和環境變數的入口,項目右擊>屬性>調試>打開調試啟動配置文件UI。用戶機密入口,項目右擊>管理用戶機密
二、通過選項方式讀取
1 //appsettings.json文件 2 { 3 "Smtp": { 4 "Server": "smtp.youzack.com", 5 "UserName": "functionMC", 6 "Password": "hello123" 7 }, 8 "Db": { 9 "DbType": "SQLServer", 10 "ConnectionString": "Data..." 11 } 12 } 13 14 15 //兩個與配置Smtp和Db關聯的類 16 //SmtpSettings.cs 17 class SmtpSettings 18 { 19 public string Server { get; set; } 20 public string UserName { get; set; } 21 public string Password { get; set; } 22 } 23 24 //DbSettings.cs 25 class DbSettings 26 { 27 public string DbType { get; set; } 28 public string ConnectionString { get; set; } 29 } 30 31 32 //配置、選項綁定,並調用一個方法來讀取配置 33 //Program.cs 34 ConfigurationBuilder configBuilder = new ConfigurationBuilder(); 35 configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange:true); 36 IConfigurationRoot config = configBuilder.Build(); 37 38 ServiceCollection services = new ServiceCollection(); 39 services.AddOptions() 40 .Configure<DbSettings>(e=>config.GetSection("Db").Bind(e)) 41 .Configure<SmtpSettings>(e=>config.GetSection("Smtp").Bind(e)); 42 43 services.AddTransient<ReadOptions>(); 44 45 using (var sp = services.BuildServiceProvider()) 46 { 47 while (true) 48 { 49 using (var scope = sp.CreateScope()) 50 { 51 var sp_scope = scope.ServiceProvider; 52 var readOptions = sp_scope.GetRequiredService<ReadOptions>(); 53 readOptions.Read(); 54 } 55 Console.WriteLine("修改appsettings後,按任意鍵讀取最新的配置"); 56 Console.ReadKey(); 57 } 58 } 59 60 61 //讀取配置的方法類 62 //ReadOptions.cs 63 class ReadOptions 64 { 65 private readonly IOptionsSnapshot<SmtpSettings> optSmtpSettings; 66 private readonly IOptionsSnapshot<DbSettings> optDbSettings; 67 68 public ReadOptions(IOptionsSnapshot<SmtpSettings> optSmtpSettings, IOptionsSnapshot<DbSettings> optDbSettings) 69 { 70 this.optSmtpSettings = optSmtpSettings; 71 this.optDbSettings = optDbSettings; 72 } 73 74 public void Read() 75 { 76 var smtp = optSmtpSettings.Value; 77 var db = optDbSettings.Value; 78 Console.WriteLine(smtp.UserName); 79 Console.WriteLine(db.DbType); 80 } 81 }
程式碼解釋:
17-29行:定義兩個類(選項類),分別映身appsettings的兩個屬性。SmtpSettings.cs映射Smtp屬性,DbSettings.cs映射Db屬性,名字一一對應
38行:構建依賴注入的容器
39-41行:註冊選項服務AddOptions,並設置「選項類和配置文件屬性」之間的映射關係。這樣寫也可以:services.AddOption;services.Configure<DbSettings>......
43行:將讀取配置的類註冊為瞬時服務(ReadOptions),這樣在後面循環讀取配置時,每次都能創建一個新的服務
45-58行:通過服務定位器的方式獲取服務(ReadOptions對象),使用了子域方式,稍顯複雜,主要目的是測試修改appsettings時的實時更新
63-81行:以依賴注入的方式,注入讀取配置的服務,注意不能直接使用SmtpSettings或DbSettings,需要使用IOptions<T>泛型介面
補充說明:
①讀取配置的泛型介面,有三種:IOptions<T>(類似單例),IOptionsMonitor<T>(類似範圍),IOptionsSnapshot<T>(類似瞬時)。以上案例,改成另外兩個,都無法實現配置資訊的實時更新。其中IOptions<T>,需要重啟應用;IOptionsMonitor<T>,重啟應用,或者修改程式碼,不在Scope中讀取
三、在ASP.NET Core中設置和讀取配置(本節有補充知識點)
1 //appsettings.json文件 2 { 3 "Smtp": { 4 "Server": "192.1.1.1", 5 "UserName": "functionMC", 6 "Password": "123456" 7 } 8 } 9 10 11 //選項類SmtpSettings.cs 12 public class SmtpSettings 13 { 14 public string Server { get; set; } 15 public string UserName { get; set; } 16 public string Password { get; set; } 17 } 18 19 20 //使用MiniApi方式,直接在Program中設置選項綁定和讀取配置 21 var builder = WebApplication.CreateBuilder(args); 22 builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp")); 23 24 var app = builder.Build(); 25 26 app.MapGet("/", (IConfiguration config,IOptions<SmtpSettings> smtpOptions) => 27 { 28 return $"直接讀取:{config["Smtp:UserName"]},選項讀取:{smtpOptions.Value.UserName}"; 29 }); 30 31 app.Run();
程式碼解釋:
21行:CreateBuilder完成一系列框架設置,包括配置體系(AddJsonFile,AddOptions等),所以不需要手動設置配置體系,框架自動設置多配置源
22行:綁定選項類和配置屬性。在Program中不方便注入,通過調用build的屬性Configuration,返回IConfiguration介面讀取配置(區別於.NET中的IConfigurationRoot)
26行:通過MiniApi的參數注入兩個服務,IConfigurations和IOptions<T>,均由框架自動註冊。如果使用控制器,可通過構造函數方式注入
28行:使用兩種方式讀取配置:直接讀取配置、通過選項方式讀取配置

