ASP.NET Core 源碼學習之 Options[1]:Configure

来源:http://www.cnblogs.com/yu-ye/archive/2017/06/21/strongly-typed-options-configure-in-asp-net-core.html
-Advertisement-
Play Games

配置的本質就是字元串的鍵值對,但是對於面向對象語言來說,能使用強類型的配置是何等的爽哉! 目錄 1. ASP.NET Core 配置系統 2. 強類型的 Options 3. Configure 方法 4. 源碼解析 ASP.NET Core 配置系統 在ASP.NET 4.X中,通常將配置存儲在 ...


配置的本質就是字元串的鍵值對,但是對於面向對象語言來說,能使用強類型的配置是何等的爽哉!

目錄

  1. ASP.NET Core 配置系統
  2. 強類型的 Options
  3. Configure 方法
  4. 源碼解析

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
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    if (configureOptions == null)
    {
        throw new ArgumentNullException(nameof(configureOptions));
    }

    services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, configureOptions));
    return services;
}

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

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
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    if (config == null)
    {
        throw new ArgumentNullException(nameof(config));
    }

    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));
        }
    }
}

那麼,大家或許會有點疑問:“ IConfigureOptions 中的 Configure 方法是在什麼時候調用的呢 ”,且看下回分解。

總結

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MySQL授權命令grant的使用方法:grant 許可權 on 資料庫對象 to 用戶 ...
  • 我們使用資料庫的時候,如果查詢條件太複雜,則會涉及到很多問題 1、無法維護,各種嵌套查詢,各種複雜的查詢,想要優化都無從下手 2、效率低下,一般語句複雜了之後,比如使用or,like %,,%查詢之後資料庫的索引就沒有辦法利用到了,這個時候的搜索就會全表掃描,數據量少的時候可能性能還能接受,但是數據 ...
  • 1.安裝好jdk。 2.打開終端。 3.sudo到root帳戶,輸入 vi /etc/profile ,打開全局配置文件。 4.在profile中添加如下配置 JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/ ...
  • 在編程或是整理知識的時候一直苦於沒有一款可以幫助理清思路的工具。 在網上苦尋良久,終於找到了一款可心可意的小軟體 —— Graphviz。 折騰了一番,終於可以湊合著用了。 現將折騰的成果記錄於此以作備忘,當然如果能夠拋磚引玉那就再好不過了。 因為本人主要使用 Windows 以下將用 Window ...
  • ubuntn預設下載路徑的源是國外的下載很慢換成國內的下載路徑會好很多 在ubuntu應用搜索框(左上腳那個)中輸入software 1.software&Updates 應用點擊software 2.在彈出的界面中的download中選擇other 3.在之後彈出的框中選到china 4.在裡面選 ...
  • Shell腳本,就是利用Shell的命令解釋的功能,對一個純文本的文件進行解析,然後執行這些功能,也可以說Shell腳本就是一系列命令的集合。Shell可以直接使用在win/Unix/Linux上面,並且可以調用大量系統內部的功能來解釋執行程式,如果熟練掌握Shell腳本,可以讓我們操作電腦變得更 ...
  • awk [-field-separator] 'commands' input-file(s) ...
  • 在.Net框架中,如果您查看所有類型的的基類:System.Object類,將找到如下4個與相等判斷的方法: static Equals() virtual Equals() static ReferenceEquals() virtual GetHashCode() 除此之外,Microsoft已 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...