以前提起配置,大家都會想到web.config和app.config,而且好像隻有這一種方式。但是在ASP.NET CORE中,不僅提供了多元化的配置方式,而且提供了監視功能。
我們這裡隻介紹幾種最常用的配置方式,最常見的配置方式應該還是配置檔案吧,畢竟使用這種方式修改配置比較友善,不需要重新編譯代碼。
1、将配置定義在appsettings.json檔案中
配置如下:
"format": {
"dateTime": {
"longDataPattern": "dddd,MMMM,d,yyyy",
"longTimePattern": "h:mm:ss tt",
"shortDataPattern": "M/d/yyyy",
"shortTimePattern": "h:mm tt"
},
"currencyDecimal": {
"digits": "5",
"symbol": "$"
}
}
然後定義一個與目前結構一緻的類:
public class FormatOptions
{
public DateTimeFormatOptions DateTime { get; set; }
public CurrencyDecimalFormatOptions CurrencyDecimal { get; set; }
}
public class DateTimeFormatOptions
{
public string LongDataPattern { get; set; }
public string LongTimePattern { get; set; }
public string ShortDataPattern { get; set; }
public string ShortTimePattern { get; set; }
}
public class CurrencyDecimalFormatOptions
{
public int Digits { get; set; }
public string Symbol { get; set; }
}
在startup的ConfigureServices方法中添加依賴注入:
services.AddOptions().Configure<FormatOptions>(Configuration.GetSection("format"));
這裡的Configuration就是startup類的全局變量
public IConfiguration Configuration { get; }
這個Configuration預設包含了appsettings.json配置檔案的内容,是以我們不需要自己建立一個ConfigurationBuilder對象,如果我們的配置不是定義在appsettings.json裡面,而是自定義了一個JSON檔案,
那我們就需要建立一個ConfigurationBuilder對象,這個我們下面會講到
這裡為什麼要調用GetSection方法呢?因為我們的appsettings.json中還有其他的配置項(項目建立時架構預設建立的配置項),我們隻取我們想要的部分,如果這裡不調用GetSection的話,也無法擷取到
配置項的值,因為我們定義的類裡面沒有架構預設的那些配置項的字段。
下面我們建立一個控制器,把IOptions<FormatOptions>作為構造函數的參數,代碼如下:
public class TestController : Controller
{
private readonly IOptions<FormatOptions> _options;
public TestController(IOptions<FormatOptions> options)
{
_options = options;
}
public string Index()
{
var value = _options.Value;
var dateTime = value.DateTime;
var currencyDecimal = value.CurrencyDecimal;
StringBuilder sb = new StringBuilder();
sb.Append($"DateTime:");
sb.Append($"\r\nlongDataPattern:{dateTime.LongDataPattern}");
sb.Append($"\r\nlongTimePattern:{dateTime.LongTimePattern}");
sb.Append($"\r\nshortDataPattern:{dateTime.ShortDataPattern}");
sb.Append($"\r\nshortTimePattern:{dateTime.ShortTimePattern}");
sb.Append($"\r\nCurrencyDecimal:");
sb.Append($"\r\ndigits:{currencyDecimal.Digits}");
sb.Append($"\r\nsymbol:{currencyDecimal.Symbol}");
return sb.ToString();
}
}
2、自定義配置檔案
某些情況下,我們可能需要将配置檔案定義在我們自定義的JSON檔案中。我們自己建立一個profile.json檔案,配置如下:
{
"gender": "Male",
"age": "33",
"contactinfo": {
"emailAddress": "foobar.outlook.com",
"phoneno": "123456789"
}
}
在startup類的ConfigureServices方法中添加依賴注入:
var configuration = new ConfigurationBuilder().AddJsonFile(path:"profile.json",optional:false,reloadOnChange:true).Build();
services.AddOptions().Configure<Profile>(configuration);
path:表示配置檔案的路徑;optional表示這個配置檔案是不是可選的,如果是的話,在程式啟動的時候架構就不會去檢查該檔案是不是存在,而且就算沒有這個檔案,程式也不會報錯,架構
也會給這個配置對應的類的所有字段賦一個預設值。如是不是可選的話,架構會檢查這個檔案是不是存在,不存在的話會報錯;reloadOnChange:如果配置檔案有改動的話,架構會重新加載
配置檔案;
這個profile類的定義就按照配置檔案給出的字段定義就好了,這些我就不把這個類的定義貼出來了。使用的方式也和上面介紹的FormatOptions一樣。如果這個配置檔案裡面還有其他的配置項,
記得調用GetSection方法擷取我們想要的部分。
3、根據運作環境動态加載配置檔案
在ASP.NET CORE中有3中運作環境:Development、Stage、Production。不同環境下配置檔案的内容可能會不同。
我們拿釋出環境做一下測試。如果目前項目還沒有appsettings.Production.json檔案,那就建立一個。
配置如下:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=_CHANGE_ME;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"format": {
"currencyDecimal": {
"digits": "6"
}
}
}
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var formatConfig = new ConfigurationBuilder().AddJsonFile(path: "appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(path: $"appsettings.{environmentName}.json", optional: false, reloadOnChange: true).Build() ;
services.AddOptions().Configure<FormatOptions>(formatConfig.GetSection("format"));
大家可以看到在appsettings.Production.json配置檔案中,我并沒有定義FormatOptions的所有字段,隻配置了CurrencyDecimalFormatOptions類裡面的Digits字段。
在建立ConfigurationBuilder類的時候,我添加了2個appsettings.json,在appsettings.json中,我定義了FormatOptions的所有字段。
在appsettings.json裡面我把Digits設定為4,而在appsettings.Production.json裡面我把Digits設定為6。然後在lanuchSettings.json中把ASPNETCORE_ENVIRONMENT
設定為Production,還是在TestController中運作,我們發現Digits字段的值等于6。
這種方式我覺得還是挺好的,把所有配置項都寫在appsettings.json檔案中,然後在與運作環境相對應的配置檔案中隻寫運作環境對應的配置項,不需要再把所有的
配置項都重寫一遍。架構會把這兩個檔案的配置項做一個合并。
4、監視配置檔案的變化
我們都希望在程式運作的過程中修改配置檔案不需要重新開機應用程式,修改的配置也能生效,ASP.NET CORE做到了這一點。
代碼其實和上面的差不多,我們要監視配置檔案的變化,隻需要把reloadOnChange屬性設定為true即可。
然後我們在消費Options對象的時候,要使用IOptionsMonitor,而不是之前的IOptions,代碼如下:
public TestController(IOptions<FormatOptions> options,IOptionsMonitor<FormatOptions> optionsMonitor)
{
_options = options;
_monitorOptions = optionsMonitor;
}
我新加了一個函數:
public string MonitorIndex()
{
var value = _monitorOptions.CurrentValue;
var dateTime = value.DateTime;
var currencyDecimal = value.CurrencyDecimal;
StringBuilder sb = new StringBuilder();
sb.Append($"DateTime:");
sb.Append($"\r\nlongDataPattern:{dateTime.LongDataPattern}");
sb.Append($"\r\nlongTimePattern:{dateTime.LongTimePattern}");
sb.Append($"\r\nshortDataPattern:{dateTime.ShortDataPattern}");
sb.Append($"\r\nshortTimePattern:{dateTime.ShortTimePattern}");
sb.Append($"\r\nCurrencyDecimal:");
sb.Append($"\r\ndigits:{currencyDecimal.Digits}");
sb.Append($"\r\nsymbol:{currencyDecimal.Symbol}");
return sb.ToString();
}
唯一的變化就是擷取值的時候使用的CurrentValue屬性。
在浏覽器中輸入/test/MonitorIndex進入到該方法,然後到程式運作的根目錄下(bin\Debug\netcoreapp3.1)修改任意一個配置項的值,儲存。
然後重新整理一下,界面就會顯示新值。如果我們還是進入到/test/index,發現修改過的配置項的值是不會變的。