問題
如何在 ASP.NET Core 2.0 應用程式中讀取全域性配置項?
答案
首先新建一個空專案,並新增兩個配置檔案:
1. appsettings.json
{ "Section1": { "SettingA": "ValueA", "SettingB": "ValueB" }, "Section2": { "SettingC": "ValueC" } }
2. appsettings.Development.json
{ "Section1": { "SettingA": "Dev_ValueA" }, "Section2": { "SettingC": "Dev_ValueC" } }
Visual Studio會自動識別兩者的關係,並在解決方案層次結構中展示如下:
然後建立相應的POCO類,分別對應於幾個配置節點:
public class AppSettings { public AppSettingsSection1 Section1 { get; set; } public AppSettingsSection2 Section2 { get; set; } } public class AppSettingsSection1 { public string SettingA { get; set; } public string SettingB { get; set; } } public class AppSettingsSection2 { public string SettingC { get; set; } }
在Startup.cs檔案中,建立接收 IConfiguration 的建構函式:
public static IConfiguration Configuration { get; private set;} public Startup(IConfiguration config) { Configuration = config; }
然後在 ConfigureServices() 方法中新增Options服務,並設定依賴項:
public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<AppSettings>(Configuration); }
最後,將配置項作為IOptions介面注入中介軟體的建構函式,其中泛型型別T就是我們剛才定義的POCO類:
public class HelloWorldMiddleware { private readonly RequestDelegate _next; private readonly AppSettings _settings; public HelloWorldMiddleware(RequestDelegate next, IOptions<AppSettings> options) { _next = next; _settings = options.Value; } public async Task Invoke(HttpContext context) { var jsonSettings = JsonConvert.SerializeObject(_settings, Formatting.Indented); await context.Response.WriteAsync(jsonSettings); } } public static class UseHelloWorldInClassExtensions { public static IApplicationBuilder UseHelloWorld(this IApplicationBuilder app) { return app.UseMiddleware<HelloWorldMiddleware>(); } }
在Startup.cs的 Configure() 方法中,將此中介軟體注入到請求管道中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHelloWorld(); }
執行,此時頁面顯示:
討論
ASP.NET Core 擁有一個簡單的機制來從各種資料來源(比如JSON檔案,環境變數,甚至是自定義資料來源)中讀取應用程式設定。然後透過依賴注入,方便的使用這些配置項。
儘管這一切看起來很魔幻(我們的設定究竟是如何載入的!),ASP.NET Core 2.0隱藏了從資料來源中讀取配置項的細節,這些內容本應該存在於Program.cs檔案中WebHost的CreateDefaultBuilder()方法中。IConfiguration隨後被新增到服務容器中,並在應用程式的其他部分保持可用,我們使用Startup中的此介面來新增配置項。為了觀察這個過程,請將Program.cs檔案中的BuildWebHost()方法替換為如下內容,得到的結果是一樣的:
public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .ConfigureAppConfiguration((context, builder) => { var env = context.HostingEnvironment; builder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); if (env.IsDevelopment()) { var appAssembly = Assembly.Load( new AssemblyName(env.ApplicationName)); if (appAssembly != null) { builder.AddUserSecrets(appAssembly, optional: true); } } builder.AddEnvironmentVariables(); if (args != null) { builder.AddCommandLine(args); } }) .Build();
在上面的解決方案中,我們提供了兩個JSON檔案資料來源。需要記著的一點是,這些檔案按照順序被依次讀取,後面的資料來源會覆蓋前面的資料來源。你也可以在上面的執行結果中注意到,SettingB配置項來自於第一個配置檔案,而其他兩個配置項都來自於第二個配置檔案。
注意:Startup.cs中的IConfiguration例項擁有public static修飾符,因此可以在整個應用程式期間使用此例項:
var valueA = Config["Section1:SettingA"];
然而,更好的辦法是將配置項讀入一個型別化的POCO類,並將其作為依賴項注入中介軟體或者控制器。上面的示例正好展示了這個模式。
你也可以為不同的配置節定義不同的POCO類,並使用IConfiguration的GetSection()方法來讀取。
====start by sanshi=========================
下面我們簡單擴充套件之前的示例,來讀取不同的配置節:
public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<AppSettings>(Configuration); services.Configure<AppSettingsSection1>(Configuration.GetSection("Section1")); }
更新中介軟體程式碼,此時向中介軟體的建構函式注入兩個依賴項:
public class HelloWorldMiddleware { private readonly RequestDelegate _next; private readonly AppSettings _settings; private readonly AppSettingsSection1 _settingsSection1; public HelloWorldMiddleware(RequestDelegate next, IOptions<AppSettings> options, IOptions<AppSettingsSection1> optionsSection1) { _next = next; _settings = options.Value; _settingsSection1 = optionsSection1.Value; } public async Task Invoke(HttpContext context) { var jsonSettings = JsonConvert.SerializeObject(_settings, Formatting.Indented); var jsonSettingsSection1 = JsonConvert.SerializeObject(_settingsSection1, Formatting.Indented); await context.Response.WriteAsync("AppSettings:\n" + jsonSettings + "\n\nAppSettings - Section1:\n" + jsonSettingsSection1); } }
執行,此時頁面顯示:
====end by sanshi=========================
當然,我們也可以手工設定配置項的值,透過使用IServiceCollection.Configure的過載方法並接收強型別的lambda表示式:
====start by sanshi=========================
修改ConfigurationServices()方法,手工設定配置項:
public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<AppSettings>(options => { options.Section1 = new AppSettingsSection1(); options.Section1.SettingA = "SettingA Value"; options.Section1.SettingB = "SettingB Value"; }); }
執行,此時頁面效果:
====end by sanshi=========================
原始碼下載
原文:https://tahirnaushad.com/2017/08/15/asp-net-core-configuration/