[譯]ASP.NET Core 2.0 全域性配置項

三生石上(FineUI控制元件)發表於2017-10-25

問題

如何在 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/

相關文章