ASP.NET Core筆記(3) - 配置

  • 配置規則
  • 命令行配置提供程序
  • 環境變量配置提供程序
  • 文件配置提供程序
  • 配置的讀取
  • 自定義配置數據源

ASP.NET Core中的配置項能夠經過命令行、環境變量、json/xml/ini配置文件來提供。json

Web應用在生成主機時會調用CreateDefaultBuilder方法,這個方法按照下面的順序添加各類配置提供程序:數據結構

  • 文件配置提供程序,用於加載appsetting.json
  • 文件配置提供程序,用於加載appsetting.{Environment}.json
  • 環境變量配置提供程序
  • 命令行配置提供程序

對於同一配置,後面加載的配置提供程序會覆蓋前面加載的內容,因此配置的默認優先級從低到高依次爲:文件 -> 環境變量 -> 命令行。app

配置規則

分層配置數據

配置 API 可以經過在配置鍵中使用分隔符來展平分層數據以保持分層配置數據。
好比,這樣的json文件:ide

{
  "section0": {
    "key0": "value",
    "key1": "value"
  },
  "section1": {
    "key0": "value",
    "key1": "value"
  }
}

配置提供程序加載時,將使用冒號 (😃 展平節和鍵,以這樣的方式建立惟一鍵以保持配置源的原始分層數據結構。ui

section0:key0
section0:key1
section1:key0
section1:key1

關於鍵和值的約定

配置鍵採用如下約定:this

  • 不區分大小寫;
  • 若是由相同或不一樣的配置提供程序設置相同鍵的值,則鍵上設置的最後一個值就是所使用的值;
  • 分層鍵默認使用冒號分隔符,但在環境變量中,冒號分隔符可能沒法適用於全部平臺,能夠用雙下劃線代替。

配置值的約定:編碼

  • 值是字符串;
  • NULL值不能存儲在配置中或綁定到對象。

命令行配置提供程序

能夠經過ConfigureHostConfiguration和ConfigureAppConfiguration方法來指定配置提供程序或者設置提供程序的優先級。
若是不須要CreateDefaultBuilder默認添加的配置提供提供程序,能夠直接刪除spa

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();
})

在ConfigurationBuilder 的實例上調用 AddCommandLine 擴展方法能夠激活命令行配置,不過CreateDefaultBuilder已經自動調用了AddCommandLine,而且命令行配置的優先級最高。若要添加其餘配置提供程序並保持可以用命令行參數替代這些提供程序的配置,能夠在ConfigureAppConfiguration中添加完其餘提供程序後,再調用一次AddCommandLine。命令行

.ConfigureAppConfiguration((hostingContext, config) =>
{
    // Call other providers here
    config.AddCommandLine(args);
})

命令行配置的設置方式爲:code

dotnet run CommandLineKey=CommandLineValue

這種設置方法使用了等號(=),也能夠用--或/做爲前綴,並空格代替等號,下面的寫法都是合理的:

dotnet run --CommandLineKey2=value2
dotnet run --CommandLineKey2 value2
dotnet run /CommandLineKey3=value3
dotnet run /CommandLineKey3 value3

環境變量配置提供程序

在ConfigurationBuilder 的實例上調用 AddEnvironmentVariables 擴展方法能夠激活環境變量配置,CreateDefaultBuilder也已經默認啓用了環境變量配置提供程序。

AddEnvironmentVariables方法還有一個重載支持加載指定前綴的環境變量。
好比

.AddEnvironmentVariables("CUSTOM_")

會只加載前綴爲CUSTOM_的環境變量。

環境變量的設置方法:

  • 命令行,set CUSTOM_ENV1=value1,但這種設置只在當前命令行窗口生效
  • 設置全局系統變量;
  • 經過visual studio,在launchSettings.json文件中設置。

文件配置提供程序

以Json文件爲例(INI、XML文件相似):

.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFile("MyConfig.json", 
            optional: true, 
            reloadOnChange: true);
          .AddJsonFile($"MyConfig.{env.EnvironmentName}.json", 
            optional: true, 
            reloadOnChange: true);
})

以這種順序添加,後面MyConfig.{env.EnvironmentName}.json中的配置會覆蓋MyConfig.json中的同名配置。

配置的讀取

GetValue

從配置中提取一個具備指定鍵的值,並將它轉換爲指定的類型

var number = Configuration.GetValue<int>("NumberKey", 99);

GetSection

會返回具備指定子節鍵的配置子節

section1 = configuration.GetSection("section1");

對於GetSection的結果,可使用GetValue 來獲取單個鍵的值,也可使用GetChild來獲取獲取子節鍵下的全部配置。

使用Get 能夠直接把配置內容綁定到類

var starship = _config.GetSection("starship").Get<Starship>();
{
  "starship": {
    "name": "USS Enterprise",
    "registry": "NCC-1701",
    "class": "Constitution",
    "length": 304.8,
    "commissioned": false,
    "Array": [ "12", "23", "d3" ],
    "ShipLog": {
      "ID": "1"
    }
  }
  ...
}
public class Starship 
{
	public string Name { get; set; }
	public string Registry { get; set; }
	public string Class { get; set; }
	public decimal Length { get; set; }
	public bool Commissioned { get; set; }
	public ShipLog ShipLog { get; set; }
	public string[] Array { get; set; }
}
public class ShipLog
{
	public string ID { get; set; }
}

自定義配置數據源

除了上述配置提供程序,還能夠自定義配置數據源,好比能夠統一從配置中心獲取配置。
要自定義配置源,須要實現IConfigurationSource和IConfigurationProvider。

實現IConfigurationSource:

class MyConfigurationSource : IConfigurationSource
{
    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new MyConfigurationProvider();
    }
}

實現IConfigurationProvider,具體方式能夠經過繼承ConfigurationProvider,而後重寫它的虛方法。下面的示例重寫了Load方法,在這裏能夠自行編碼獲取配置、設置到this.Data,Data是一個鍵和值類型都是string的字典,用於存儲配置。還用了一個定時器來模擬配置的變動,在發生配置變動時,觸發base.OnReload();

class MyConfigurationProvider : ConfigurationProvider
{
    Timer timer;

    public MyConfigurationProvider() : base()
    {
        timer = new Timer();
        timer.Elapsed += (a, b) => Load(true);
        timer.Interval = 3000;
        timer.Start();
    }

    public override void Load()
    {
        //加載數據
        Load(false);
    }

    void Load(bool reload)
    {
        this.Data["lastTime"] = DateTime.Now.ToString();            
        if (reload)
        {
            base.OnReload();
        }
    }
}

使用的時候:builder.Add(new MyConfigurationSource());

但這種方法會暴露具體的實現,能夠封裝爲擴展方法。若是把這個擴展類的命名空間指定爲Microsoft.Extensions.Configuration,這樣在分發到第三方後,就能夠直接使用,而沒必要using程序集的命名空間,而前面的實現類默認爲internal,第三方沒法訪問到,實現了整個類庫只暴露出一個擴展方法的效果。

namespace Microsoft.Extensions.Configuration
{
    public static class MyConfigurationBuilderExtensions
    {
        public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder)
        {
            builder.Add(new MyConfigurationSource());
            return builder;
        }
    }
}

監聽配置變動的方法:

builder.AddMyConfiguration();
var configRoot = builder.Build();
ChangeToken.OnChange(() => configRoot.GetReloadToken(), () =>
{
    //監聽到配置變動後的處理代碼
});
相關文章
相關標籤/搜索