日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 源码学习之 Options[1]:Configure

發布時間:2023/12/4 asp.net 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 源码学习之 Options[1]:Configure 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

而不指定name的Configure和ConfigureAll方法,都只是一種簡寫形式,使用默認的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 方法是在什么時候調用的呢 ”,這個且看下章分解。

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 (options == null){ ? ? ? ?
? ?? ?throw new ArgumentNullException(nameof(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 源码学习之 Options[1]:Configure的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。