正如大家所知,在 .NET Core 中配置文件改成了 appsettings.json舆吮,表面上和 .NET Framework 的 web.config 或 app.config 好像沒有太大的區(qū)別,只是一種是 json 辱挥,一種是 xml,但其實 .NET Core 的配置體系是一種全新的設(shè)計吻氧,靈活且具擴展性僚匆。這里主要介紹一下在 .NET Core 的配置體系下如何擴展自定義配置源憋飞,配置源其實就是配置信息存放的載體,最常用的就是文件類型争剿。
.NET Core 配置體系
在進行自定義配置源介紹前已艰,我們需要先了解一下 .NET Core 中的配置體系。 .NET Core 的配置體系中主要包含 ConfigurationProvider
蚕苇、ConfigurationSource
哩掺、ConfigurationBuilder
、Configuration
幾大核心對象涩笤。
ConfigurationProvider
實現(xiàn) IConfigurationProvider
接口嚼吞,配置源真正提供者,主要提供配置信息的加載與刷新蹬碧。
ConfigurationSource
實現(xiàn) IConfigurationSource
接口舱禽,提供對應(yīng)的 ConfigurationProvider
具體實例。
ConfigurationBuilder
實現(xiàn) IConfigurationBuilder
接口恩沽,負責(zé)將 ConfigurationSource
添加到配置源集合誊稚,再根據(jù)配置源集合構(gòu)建出 ConfigurationRoot
對象,實現(xiàn) IConfigurationRoot
接口罗心。
Configuration
實現(xiàn) IConfiguration
接口片吊,Configuration
對象在邏輯上體現(xiàn)出樹形化層次結(jié)構(gòu),配置信息均以鍵/值對的方式提供使用协屡。
注 :IConfigurationRoot
、IConfigurationSection
均繼承于 IConfiguration
全谤,IConfigurationRoot
表示配置的根節(jié)點肤晓,IConfigurationSection
則表示配置的非根節(jié)點
所以他們之間的關(guān)系就是 ConfigurationProvider
實現(xiàn)配置提供,然后通過 ConfigurationSource
構(gòu)造配置源實例,接著通過 ConfigurationBuilder
將配置源實例 ConfigurationSource
添加到配置源集合中并構(gòu)造出 ConfigurationRoot
补憾,最終以 Configuration
對象提供給程序使用漫萄。
默認(rèn)情況下,Configuration
對象的 Providers
屬性包含如下 Provider
:
-
ChainedConfigurationProvider
:應(yīng)用程序本身相關(guān)配置信息盈匾,如:applicationName腾务、contentRoot; -
JsonConfigurationProvider
:appsettings.json 和 appsettings.Development.json 中的配置信息削饵; -
EnvironmentVariablesConfigurationProvider
:環(huán)境變量的配置信息岩瘦; -
CommandLineConfigurationProvider
:命令行輸入的配置信息;
這些類型的 Provider 在 .NET Core Web 項目中默認(rèn)會自動加載窿撬,不需要手動配置启昧,當(dāng)然預(yù)置的 Provider 并不止這幾種。
自定義配置源
前面提到 .NET Core 的配置體系是具有擴展性的劈伴,所以我們可以實現(xiàn)自定義的配置源密末,比如基于配置中心(如:etcd、apollo跛璧、consul 等)的實現(xiàn)严里,下面將模擬從配置中心獲取,先了解整體實現(xiàn)方式追城,后面也會介紹我們在實際項目中基于 etcd 的實現(xiàn)方案刹碾。
創(chuàng)建 ConfigurationProvider
自定義 Provider 需要繼承 ConfigurationProvider
,然后重寫 Load
方法漓柑,設(shè)置 Data
屬性教硫。
public class CustomConfigurationProvider : ConfigurationProvider
{
public override void Load()
{
// 模擬從遠程配置中心獲取配置信息
using var httpClient = new HttpClient
{
BaseAddress = new Uri("http://localhost:5000")
};
var response = httpClient.GetStringAsync("/api/configs")
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
if (!string.IsNullOrEmpty(response))
{
Data = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
}
}
}
http://localhost:5000/api/configs 接口返回的 json 字符串,如下:
{"name":"beck","company":"mingdao"}
創(chuàng)建 ConfigurationSource
實現(xiàn) IConfigurationSource
接口辆布,在 Build
方法中返回 CustomConfigurationProvider
實例瞬矩。
public class CustomConfigurationSource : IConfigurationSource
{
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new CustomConfigurationProvider();
}
}
加入 ConfigurationBuilder 配置源列表
添加 IConfigurationBuilder
擴展方法 AddCustom
,將 CustomConfigurationSource
加入配置源集合中锋玲。
public static class CustomConfigurationExtensions
{
public static IConfigurationBuilder AddCustom(this IConfigurationBuilder builder)
{
return builder.Add(new CustomConfigurationSource());
}
}
啟動入口添加 AddCustom
在 Program.cs
中的 ConfigureAppConfiguration
引用自定義配置源:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureAppConfiguration((context, configBuiler) =>
{
configBuiler.AddCustom();
});
webBuilder.UseStartup<Startup>();
});
測試效果
再次查看 Configuration
對象的 Providers
屬性景用,發(fā)現(xiàn)已包含 CustomConfigurationProvider
:
然后可通過 Configuration
對象獲取對應(yīng) key
的內(nèi)容:
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { _configuration["name"], _configuration["company"] };
}
總結(jié)
以上完成了一個簡單的自定義配置源,實際情況會比這復(fù)雜些惭蹂。如果關(guān)注過 JsonConfigurationProvider
的配置加載參數(shù)伞插,有一個 reloadOnChange
參數(shù)用來設(shè)置當(dāng)配置文件有變化時是否重新加載,如果 reloadOnChange
設(shè)置為 true盾碗,當(dāng)配置文件變化時不需要重啟服務(wù)就可以生效媚污,很多時候我們是需要 Provider 具有這個功能的,在接下來介紹的 EtcdConfigurationProvider
中會實現(xiàn)廷雅,實現(xiàn)源碼 已在 Github 可供參考耗美。