ASP.NET Core中的Options选项模式

作者:暗断肠 时间:2024-05-13 09:16:59 

1.前言

选项(Options)模式是对配置(Configuration)的功能的延伸。在12章(ASP.NET Core中的配置二)Configuration中有介绍过该功能(绑定到实体类、绑定至对象图、将数组绑定至类)而选项模式又有个选项类(TOptions),该选项类作用是指:把选项类中的属性与配置来源中的键关联起来。举个例,假设json文件有个Option1键,选项类中也有个叫Option1的属性名,经过选项配置,这样就能把json中的键的值映射到选项类属性值中。也可以理解在项目应用中,把一个json文件序列化到.net类。

2.常规选项配置

选项类必须为包含公共无参数构造函数的非抽象类。在appsettings.json文件中添加option1、option2、subsection的配置:

{
 "option1": "value1_from_json",
 "option2": -1,
 "subsection": {
   "suboption1": "subvalue1_from_json",
   "suboption2": 200
 },
 "Logging": {
   "LogLevel": {
     "Default": "Warning"
   }
 },
 "AllowedHosts": "*"
}

新建MyOptions类(Models/MyOptions.cs),以下类MyOptions具有三种属性:Option1和 Option2。设置默认值为可选,但以下示例中的类构造函数设置了Option1的默认值。Option2具有通过直接初始化属性设置的默认值:

public class MyOptions
{
   public MyOptions()
   {
       // Set default value.
       Option1 = "value1_from_ctor";
   }
   public string Option1 { get; set; }
   public int Option2 { get; set; } = 5;
}

而MyOptions类通过Configure添加到服务容器并绑定到配置:

public void ConfigureServices(IServiceCollection services)
{
   // Example #1: General configuration
   // Register the Configuration instance which MyOptions binds against.
   services.Configure<MyOptions>(Configuration);
}

也可以使用自定义ConfigurationBuilder从设置文件加载选项配置时,确认基路径设置正确,添加到服务容器并绑定到配置:

var configBuilder = new ConfigurationBuilder()
  .SetBasePath(Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional: true);
var config = configBuilder.Build();
services.Configure<MyOptions>(config);

以下页面模型通过IOptionsMonitor<TOptions>使用构造函数依赖关系注入来访问设置 (Pages/Index.cshtml.cs):

public class IndexModel
{
   public IndexModel(IOptionsMonitor<MyOptions> optionsAccessor)
   {
       _options = optionsAccessor.CurrentValue;
   }
   private readonly MyOptions _options;
   public void OnGet()
   {
       // Example #1: Simple options
       var option1 = _options.Option1;
       var option2 = _options.Option2;
       var simpleOptions = $"option1 = {option1}, option2 = {option2}";
   }
}

在Home/Index控制器Action下调用IndexModel.OnGet方法返回包含选项值的字符串:

public HomeController(IOptionsMonitor<MyOptions> optionsAccessor)
{
   _optionsAccessor = optionsAccessor;
}
private readonly IOptionsMonitor<MyOptions> _optionsAccessor;
public IActionResult Index()
{
   IndexModel indexModel = new IndexModel(_optionsAccessor);
   indexModel.OnGet();
   return View();
}

ASP.NET Core中的Options选项模式

3.通过委托配置简单选项

使用委托设置选项值。此示例应用程序使用新建MyOptionsWithDelegateConfig类 (Models/MyOptionsWithDelegateConfig.cs):

public class MyOptionsWithDelegateConfig
{
   public MyOptionsWithDelegateConfig()
   {
       // Set default value.
       Option1 = "value1_from_ctor";
   }
   public string Option1 { get; set; }
   public int Option2 { get; set; } = 5;
}

向服务容器添加IConfigureOptions<TOptions>服务。它通过MyOptionsWithDelegateConfig使用委托来配置绑定:

public void ConfigureServices(IServiceCollection services)
{
   // Example #2: Options bound and configured by a delegate
   services.Configure<MyOptionsWithDelegateConfig>(myOptions =>
   {
       myOptions.Option1 = "value1_configured_by_delegate";
       myOptions.Option2 = 500;
   });
}

以下页面模型通过IOptionsMonitor<TOptions>使用构造函数依赖关系注入来访问设置 (Pages/Index.cshtml.cs):

public class IndexModel
{
   private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig;
   public IndexModel(IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig)
   {
       _optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
   }
   public void OnGet()
   {
       // Example #2: Options configured by delegate
       var delegate_config_option1 = _optionsWithDelegateConfig.Option1;
       var delegate_config_option2 = _optionsWithDelegateConfig.Option2;
       var simpleOptionsWithDelegateConfig =
               $"delegate_option1 = {delegate_config_option1}, " +
               $"delegate_option2 = {delegate_config_option2}";
   }
}

在Home/Index控制器Action下调用IndexModel.OnGet方法返回包含选项值的字符串:

public HomeController(IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig)
{
   _optionsAccessorWithDelegateConfig = optionsAccessorWithDelegateConfig;
}
private readonly IOptionsMonitor<MyOptionsWithDelegateConfig> _optionsAccessorWithDelegateConfig;
public IActionResult Index()
{
   IndexModel indexModel = new IndexModel(_optionsAccessorWithDelegateConfig);
   indexModel.OnGet();
   return View();
}

ASP.NET Core中的Options选项模式

每次调用Configure都会将IConfigureOptions<TOptions>服务添加到服务容器。在前面的示例中,Option1和Option2的值同时在appsettings.json中指定,但Option1和Option2的值被配置的委托替代。当启用多个配置服务时,指定的最后一个配置源优于其他源,由其设置配置值。运行应用程序时,页面模型的OnGet方法返回显示选项类值的字符串。

4.子选项配置

将选项绑定到配置时,选项类型中的每个属性都将绑定到窗体property[:sub-property:]的配置键。例如,MyOptions.Option1属性将绑定到从appsettings.json中的option1属性读取的键Option1。在以下代码中,已向服务容器添加IConfigureOptions<TOptions>服务。它将MySubOptions绑定到appsettings.json文件的subsection部分:

public void ConfigureServices(IServiceCollection services)
{
   // Example #3: Suboptions
   // Bind options using a sub-section of the appsettings.json file.
   services.Configure<MySubOptions>(Configuration.GetSection("subsection"));
}

新建MySubOptions类(Models/MySubOptions.cs)将属性SubOption1和SubOption2定义为保留选项值:

public class MySubOptions
{
   public MySubOptions()
   {
       // Set default values.
       SubOption1 = "value1_from_ctor";
       SubOption2 = 5;
   }
   public string SubOption1 { get; set; }
   public int SubOption2 { get; set; }
}

以下页面模型通过IOptionsMonitor<TOptions>使用构造函数依赖关系注入来访问设置(Pages/Index.cshtml.cs):

public class IndexModel
{
   private readonly MySubOptions _subOptions;
   public IndexModel(IOptionsMonitor<MySubOptions> subOptionsAccessor)
   {
       _subOptions = subOptionsAccessor.CurrentValue;
   }
   public void OnGet()
   {
       // Example #3: Suboptions
       var subOption1 = _subOptions.SubOption1;
       var subOption2 = _subOptions.SubOption2;
       var subOptions = $"subOption1 = {subOption1}, subOption2 = {subOption2}";
   }
}

在Home/Index控制器Action下调用IndexModel.OnGet方法返回包含选项值的字符串:

public HomeController(IOptionsMonitor<MySubOptions> subOptionsAccessor)
{
   _subOptionsAccessor = subOptionsAccessor;
}
private readonly IOptionsMonitor<MySubOptions> _subOptionsAccessor;
public IActionResult Index()
{
   IndexModel indexModel = new IndexModel(_subOptionsAccessor);
   indexModel.OnGet();
   return View();
}

ASP.NET Core中的Options选项模式

5.通过IOptionsSnapshot重新加载配置数据

IOptionsSnapshot针对请求生命周期访问和缓存选项时,每个请求只能计算一次选项。以下示例演示如何在更改appsettings.json(Pages/Index.cshtml.cs)后创建新的 IOptionsSnapshot<TOptions>。在更改appsettings.json文件和重新加载配置之前,针对服务器的多个请求返回appsettings.json文件提供的配置键值。

public class IndexModel
{
   private readonly MyOptions _snapshotOptions;
   public IndexModel(IOptionsSnapshot<MyOptions> snapshotOptionsAccessor)
   {
       _snapshotOptions = snapshotOptionsAccessor.Value;
   }
   public void OnGet()
   {
       // Example #5: Snapshot options
       var snapshotOption1 = _snapshotOptions.Option1;
       var snapshotOption2 = _snapshotOptions.Option2;
       var snapshotOptions = $"snapshot option1 = {snapshotOption1}, " + $"snapshot option2 = {snapshotOption2}";
   }
}

下面显示从appsettings.json文件加载的初始option1和option2值:

snapshot option1 = value1_from_json, snapshot option2 = -1

将appsettings.json文件中的值更改为value1_from_json UPDATED和200。保存appsettings.json 文件。刷新浏览器,查看更新的选项值:

snapshot option1 = value1_from_json UPDATED, snapshot option2 = 200

6.包含IConfigureNamedOptions的命名选项支持

命名选项支持允许应用程序在命名选项配置之间进行区分。命名选项通过OptionsServiceCollectionExtensions.Configure进行声明,其调用扩展方法ConfigureNamedOptions<TOptions>.Configure:

public void ConfigureServices(IServiceCollection services)
{
   // Example #6: Named options (named_options_1)
   // Register the ConfigurationBuilder instance which MyOptions binds against.
   // Specify that the options loaded from configuration are named
   // "named_options_1".
   services.Configure<MyOptions>("named_options_1", Configuration);

// Example #6: Named options (named_options_2)
   // Specify that the options loaded from the MyOptions class are named
   // "named_options_2".
   // Use a delegate to configure option values.
   services.Configure<MyOptions>("named_options_2", myOptions =>
   {
       myOptions.Option1 = "named_options_2_value1_from_action";
   });
}

通过OnGet(Pages/Index.cshtml.cs)访问命名选项:

public class IndexModel
{
   private readonly MyOptions _named_options_1;
   private readonly MyOptions _named_options_2;
   public IndexModel(IOptionsSnapshot<MyOptions> namedOptionsAccessor)
   {
       _named_options_1 = namedOptionsAccessor.Get("named_options_1");
       _named_options_2 = namedOptionsAccessor.Get("named_options_2");
   }
   public void OnGet()
   {
       // Example #6: Named options
       var named_options_1 =
           $"named_options_1: option1 = {_named_options_1.Option1}, " +
           $"option2 = {_named_options_1.Option2}";
       var named_options_2 =
           $"named_options_2: option1 = {_named_options_2.Option1}, " +
           $"option2 = {_named_options_2.Option2}";
       var namedOptions = $"{named_options_1} {named_options_2}";
   }
}

在Home/Index控制器Action下调用IndexModel.OnGet方法返回包含选项值的字符串:

public HomeController(IOptionsSnapshot<MyOptions> namedOptionsAccessor)
{
   _namedOptionsAccessor = namedOptionsAccessor;
}
private readonly IOptionsSnapshot<MyOptions> _namedOptionsAccessor;
public IActionResult Index()
{
   IndexModel indexModel = new IndexModel(_namedOptionsAccessor);
   indexModel.OnGet();
   return View();
}

ASP.NET Core中的Options选项模式

使用ConfigureAll方法配置所有选项

使用ConfigureAll方法可以配置所有选项实例。以下代码将针对包含公共值的所有配置实例配置Option1。将以下代码手动添加到Startup.ConfigureServices方法:

services.ConfigureAll<MyOptions>(myOptions =>
{
   myOptions.Option1 = "ConfigureAll replacement value";
});

在Home/Index控制器Action下调用IndexModel.OnGet方法返回包含选项值的字符串:

ASP.NET Core中的Options选项模式

来源:https://www.cnblogs.com/wzk153/p/11307014.html

标签:ASP.NET,Core,Options,选项,模式
0
投稿

猜你喜欢

  • Python 可迭代对象 iterable的具体使用

    2021-08-28 08:24:32
  • Python数字比较与类结构

    2023-07-29 13:33:51
  • 手把手带你走进Go语言之常量解析

    2024-05-08 10:44:38
  • python 找出list中最大或者最小几个数的索引方法

    2022-08-12 13:23:11
  • gridview生成时如何去掉style属性中的border-collapse

    2024-04-18 09:36:56
  • Python合并字典键值并去除重复元素的实例

    2022-02-10 17:48:40
  • Python正则表达式中的量词符号与组问题小结

    2022-12-14 15:24:24
  • CSS背景图片的运用优化HTTP连接数

    2008-09-04 21:38:00
  • mysql 不等于 符号写法

    2024-01-22 07:03:06
  • Python实现随机生成任意数量车牌号

    2022-08-04 04:53:17
  • Python通过DOM和SAX方式解析XML的应用实例分享

    2023-10-15 10:46:32
  • python之列表推导式的用法

    2021-04-22 18:54:59
  • Python实现带百分比的进度条

    2022-03-10 00:43:47
  • 解决golang在import自己的包报错的问题

    2024-04-25 15:09:19
  • vue 实现特定条件下绑定事件

    2023-07-02 16:39:42
  • python实现的用于搜索文件并进行内容替换的类实例

    2022-01-07 13:50:43
  • Python中assert函数的使用(含源代码)

    2022-07-18 19:46:49
  • 对python3.4 字符串转16进制的实例详解

    2022-03-29 16:15:17
  • Pygame游戏开发之太空射击实战碰撞改进篇

    2022-11-19 03:04:52
  • Mysql性能优化案例研究-覆盖索引和SQL_NO_CACHE

    2024-01-25 12:58:00
  • asp之家 网络编程 m.aspxhome.com