1. 程式人生 > >ASP.NET Core 2.1 原始碼學習之 Options[1]:Configure

ASP.NET Core 2.1 原始碼學習之 Options[1]:Configure

配置的本質就是字串的鍵值對,但是對於面嚮物件語言來說,能使用強型別的配置是何等的爽哉!

目錄

  1. ASP.NET Core 配置系統
  2. 強型別的 Options
  3. Configure 方法
  4. ConfigureNamedOptions

ASP.NET Core 配置系統

在ASP.NET 4.X中,通常將配置儲存在 web.config 中,使用靜態幫助類來獲取這些配置,而對 web.cofng 中進行任何修改時,則會導致應用程式池的回收,這種實現方式並不是很友好。

因此,在ASP.NET Core中,對配置系統進行了重寫,仍然使用的是基本的鍵值對,但是它們可以從多種格式的配置源中來獲取,比如:命令列、環境變數、XML檔案、JSON檔案等等,你也可以編寫自定義的配置源提供程式。

通常在Stratup類的建構函式中對配置源進行設定:

public Startup(IHostingEnvironment env)  
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; }  

首先建立了一個ConfigurationBuilder,然後設定配置源,最終生成的Configuration是所有配置源中的鍵值對組合。

你可以直接在程式中使用IConfigurationRoot來讀取配置,但是建議你使用強型別的Options,這樣在你想獲取某個配置時,只需要注入對應的Options,而不是獲取整個配置。

強型別的 Options

Options is a framework for accessing and configuring POCO settings.

簡單來說,Options 就是將一個 POCO 的配置類,通過在Startup類中註冊到容器中,在後續使用的時候使用建構函式注入來獲取到POCO物件。我們將這種程式設計模式稱為Options模式

首先定義一個 Options

public class MyOptions
{
    public string DefaultValue { get; set; }
}

然後我們在對應的appsettings.json中新增如下片段:

{
  "MyOptions": {
    "DefaultValue" : "first"
  }
}

Startup中的ConfigureServices方法中,進行服務的註冊:

public void ConfigureServices(IServiceCollection services)  
{
    services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));
}

最後,便在控制器中注入IOptions<MyOptions>,通過其Value屬性對MyOptions進行訪問:

[Route("api/[controller]")]
public class ValuesController : Controller  
{
    private readonly MyOptions _options;
    public ValuesController(IOptions<MyOptions> options)
    {
        _options = options.Value;
    }

    [HttpGet]
    public string Get()
    {
        return _options.DefaultValue;
    }
}

Configure 方法

Options框架為我們提供了一系統的IServiceCollection的擴充套件方法,方便我們的使用。

直接使用Action配置

// 最簡單的註冊方式
services.Configure<MyOptions>(o => o.DefaultValue = true);

// 指定具體名稱
services.Configure<MyOptions>("my", o => o.DefaultValue = true);

// 配置所有例項
services.ConfigureAll<MyOptions>(o => o.DefaultValue = true);

通過配置檔案進行配置

// 使用配置檔案來註冊例項
services.Configure<MyOptions>(Configuration.GetSection("Sign"));

// 指定具體名稱
services.Configure<MyOptions>("my", Configuration.GetSection("Sign"));

// 配置所有例項
services.ConfigureAll<MyOptions>(Configuration.GetSection("Sign"));

PostConfigure方法

PostConfigure 方法在 Configure 方法之後執行,是2.0中新增加的。

services.PostConfigure<MyOptions>(o => o.DefaultValue = true);
services.PostConfigure<MyOptions>("smyign", o => o.DefaultValue = true);
services.PostConfigureAll<MyOptions>(o => o.DefaultValue = true);

原始碼解析

首先看一下IConfigureOptions介面:

public interface IConfigureOptions<in TOptions> where TOptions : class
{
    void Configure(TOptions options);
}

Configure擴充套件方法中便是為IConfigureOptions<>註冊了一個單例ConfigureNamedOptions<>

public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions)
    where TOptions : class
{
    services.AddOptions();
    services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, configureOptions));
    return services;
}

而不指定nameConfigureConfigureAll方法,都只是一種簡寫形式,使用預設的DefaultName

public static class Options
{
    public static readonly string DefaultName = string.Empty;
}

public static IServiceCollection Configure<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class 
=> services.Configure(Options.Options.DefaultName, configureOptions);

public static IServiceCollection ConfigureAll<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
=> services.Configure(name: null, configureOptions: configureOptions);

如上,Configure方法其實就是為IConfigureOptions<>註冊了一個單例ConfigureNamedOptions<>

再看一下使用IConfiguration進行配置的擴充套件方法:

public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config)
    where TOptions : class
{
    services.AddOptions();
    services.AddSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(name, config));
    return services.AddSingleton<IConfigureOptions<TOptions>>(new NamedConfigureFromConfigurationOptions<TOptions>(name, config));
}

可以看到,註冊的例項變成了NamedConfigureFromConfigurationOptions,而其本質依然是呼叫ConfigureNamedOptions,只不過Action的方法體變成了ConfigurationBinder.Bind()

public class NamedConfigureFromConfigurationOptions<TOptions> : ConfigureNamedOptions<TOptions>
    where TOptions : class
{
    public NamedConfigureFromConfigurationOptions(string name, IConfiguration config)
        : base(name, options => ConfigurationBinder.Bind(config, options))
    {
        if (config == null)
        {
            throw new ArgumentNullException(nameof(config));
        }
    }
}

在上面的Configure方法中,都呼叫了AddOptions,我們來看一下:

public static IServiceCollection AddOptions(this IServiceCollection services)
{
    services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>)));
    services.TryAdd(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsManager<>)));
    services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>)));
    services.TryAdd(ServiceDescriptor.Transient(typeof(IOptionsFactory<>), typeof(OptionsFactory<>)));
    services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>)));
    return services;
}

如上便是Options系統的幾個核心物件了,後續章節再來一一介紹。

大家或許會有點疑問:“ IConfigureOptions 中的 Configure 方法是在什麼時候呼叫的呢 ”,這個且看下章分解。

ConfigureNamedOptions

ConfigureNamedOptions 實現了 IConfigureNamedOptions,而 IConfigureNamedOptions 則是對 IConfigureOptions 的一個擴充套件,添加了Name引數,這樣,我們便可以為同一個 Options 型別註冊多個獨立的例項,在某些場景下則是非常有用的。有關Name的使用,則會在 第三章 來講。

public interface IConfigureNamedOptions<in TOptions> : IConfigureOptions<TOptions> where TOptions : class
{
    void Configure(string name, TOptions options);
}

再看一下 ConfigureNamedOptions 的原始碼:

public class ConfigureNamedOptions<TOptions> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class
{
    public ConfigureNamedOptions(string name, Action<TOptions> action)
    {
        Name = name;
        Action = action;
    }

    public string Name { get; }

    public Action<TOptions> Action { get; }

    public virtual void Configure(string name, TOptions options)
    {
        if (Name == null || name == Name)
        {
            Action?.Invoke(options);
        }
    }

    public void Configure(TOptions options) => Configure(Options.DefaultName, options);
}

ConfigureNamedOptions 本質上就是把我們註冊的Action包裝成統一的Configure方法,以方便後續建立Options例項時,進行初始化。

總結

本文描述了在 .NET Core 配置系統中Options的配置及原理,在 下一章 來講一下IOptions的使用。

相關推薦

ASP.NET Core 2.1 原始碼學習 Options[1]:Configure

配置的本質就是字串的鍵值對,但是對於面嚮物件語言來說,能使用強型別的配置是何等的爽哉! 目錄 ASP.NET Core 配置系統 強型別的 Options Configure 方法 ConfigureNamedOptions ASP.NET Core 配置系統 在ASP.NET 4.X中,通常將配置儲

ASP.NET Core 2.0系列學習筆記-NLog日誌配置檔案

一、新建ASP.NET Core 2.0 MVC專案,使用NuGet在瀏覽中搜索:NLog.Web.AspNetCore,如下圖所示:二、在專案的bin\Debug\netcoreapp2.0\下新建一個xml型別的nlog.config檔案,如下圖(結合上圖觀看):nlog

從頭編寫 asp.net core 2.0 web api 基礎框架 (1)

工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.Chrome (最好是) 關於.net core或者.net core 2.0的相關知識就不介紹了, 這裡主要是從頭編寫一個asp.net core 2.0 web api的基礎框架.

除錯 ASP.NET Core 2.0 原始碼

在Visual Studio 2017中可以通過符號以及源連結,非常方便對 ASP.NET Core 2.0中原始碼進行除錯。在這篇文章中,我們將重點介紹如何使用源連結對ASP.NET Core源進行除錯。 什麼是源連結? 和我一樣,您可能已經注意到在編譯程式碼時,會建立的PDB檔案。這些檔案儲存了符

【轉載】從頭編寫 asp.net core 2.0 web api 基礎框架 (1)

asp.net studio 依賴 ole hand 為我 dev 工具 項目 【轉載】從頭編寫 asp.net core 2.0 web api 基礎框架 (1) 工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (

ASP.NET Core 選項模式原始碼學習Options Configure(一)

前言 ASP.NET Core 後我們的配置變得更加輕量級了,在ASP.NET Core中,配置模型得到了顯著的擴充套件和增強,應用程式配置可以儲存在多環境變數配置中,appsettings.json使用者機密等 並可以通過應用程式中的相同介面輕鬆訪問,除此之外,ASP.NET中的新配置系統允許使用Opt

ASP.NET Core 選項模式原始碼學習Options IOptions(二)

前言 上一篇文章介紹IOptions的註冊,本章我們繼續往下看 IOptions IOptions是一個接口裡面只有一個Values屬性,該介面通過OptionsManager實現 public interface IOptions<out TOptions> where TOpt

ASP.NET Core 選項模式原始碼學習Options IOptionsMonitor(三)

前言 IOptionsMonitor 是一種單一示例服務,可隨時檢索當前選項值,這在單一例項依賴項中尤其有用。IOptionsMonitor用於檢索選項並管理TOption例項的選項通知, IOptionsMonitor 支援以下方案: 更改通知 命名選項 可過載配置 選擇性選項失效 (IOptions

ASP.NET Core 原始碼學習 Logging[1]:Introduction

在ASP.NET 4.X中,我們通常使用 log4net, NLog 等來記錄日誌,但是當我們引用的一些第三方類庫使用不同的日誌框架時,就比較混亂了。而在 ASP.Net Core 中內建了日誌系統,並提供了一個統一的日誌介面,ASP.Net Core 系統以及其它第三方類庫等都使用這個日誌介面來記錄日誌,而

Asp.net core 2.0.1 Razor 的使用學習筆記(一)

提升 完成後 安全 provider razor 官方 one text .cn 環境:vs2017 版本:15.5.6 這裏說明下, Razor頁面模式跟mvc出現了嚴重的不同。正如微軟官方說的一樣“Razor 頁面是 ASP.NET Core MVC 的一

Asp.net core 2.0.1 Razor 的使用學習筆記(三)

post 應用程序 新的 entity gin start 密碼強度 ice httponly ASP.net core 2.0.1 中 asp.net identity 2.0.1 的基本使用(二)—用戶賬戶及cookie配置 修改用戶賬戶及cookie配置

學習 ASP.NET Core 2.1:集成測試中使用 WebApplicationFactory

UNC enc sta 測試 修改 構造 creat -a msdn WebApplicationFactory 是 ASP.NET Core 2.1 新特性 MVC functional test infrastructure 中帶來的新東東,它封裝了 TestServe

從零開始學習 asp.net core 2.1 web api 後端api基礎框架(七)-新增一個查詢單筆資料的方法

再寫一個查詢單筆資料的方法: [Route("{id}")] public JsonResult GetProduct(int id) { return new JsonResult(ProductService.Curre

從零開始學習 asp.net core 2.1 web api 後端api基礎框架(六)-把獲取資料的程式碼整理成一個服務

建立一個Services目錄, 然後建立一個 ProductService.cs類 我們把獲取資料的程式碼整理成一個ProductService, 然後保證程式執行的時候, 操作的是同一批資料: namespace CoreBackend.Api.Services { public

從零開始學習 asp.net core 2.1 web api 後端api基礎框架(五)-Routing 路由

路由有兩種方式: Convention-based (按約定), attribute-based(基於路由屬性配置的).  其中convention-based (基於約定的) 主要用於MVC (返回View或者Razor Page那種的). Web api 推薦使用attribute

ABP框架(asp.net core 2.X+Vue)模板專案學習路(一)

      前言:   第一次接觸ABP的專案是在2018年6月份,但是當時沒有深入具體的研究,而今天因為工作的需要,需要學習、瞭解這個框架,在時隔半年之後,今天重新下載了這個專案,雖然在園子裡有很多前輩們寫的這類的文章,但是我還是會在部落格園中記錄一下學習的過程,一是希

從零開始學習 asp.net core 2.1 web api 後端api基礎框架(四)-建立Controller

建立一個Controllers目錄, 然後建立一個“控制器類” ProductController.cs, 它需要繼承Microsoft.AspNetCore.Mvc.Controller 在Controller裡面寫這個Get方法: namespace CoreBack

一起學ASP.NET Core 2.0學習筆記(一): CentOS下 .net core2 sdk nginx、supervisor、mysql環境搭建

image dev 預覽 def star fig brush rest aspnet 作為.neter,看到.net core 2.0的正式發布,心裏是有點小激動的,迫不及待的體驗了一把,發現速度確實是快了很多,其中也遇到一些小問題,所以整理了一些學習筆記: 閱讀目

一起學ASP.NET Core 2.0學習筆記(二): ef core2.0 及mysql provider 、Fluent API相關配置及遷移

upd order rac option 包管理 rtl code create .net core 不得不說微軟的技術叠代還是很快的,上了微軟的船就得跟著她走下去,前文一起學ASP.NET Core 2.0學習筆記(一): CentOS下 .net core2 s

ASP.NET Core 2 學習筆記(十)視圖

部分 合成 cati 分享 col script text var AC ASP.NET Core MVC中的Views是負責網頁顯示,將數據一並渲染至UI包含HTML、CSS等。並能痛過Razor語法在*.cshtml中寫渲染畫面的程序邏輯。本篇將介紹ASP.NET Co