欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(13)ASP.NET Core 中的选项模式(Options)

程序员文章站 2022-04-10 15:37:41
1.前言 选项(Options)模式是对配置(Configuration)的功能的延伸。在12章(ASP.NET Core中的配置二)Configuration中有介绍过该功能(绑定到实体类、绑定至对象图、将数组绑定至类)而选项模式又有个选项类(TOptions),该选项类作用是指:把选项类中的属性 ......

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

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

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

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

(13)ASP.NET Core 中的选项模式(Options)

5.1使用configureall方法配置所有选项

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

services.configureall<myoptions>(myoptions =>
{
    myoptions.option1 = "configureall replacement value";
});

在home/index控制器action下调用indexmodel.onget方法返回包含选项值的字符串:

(13)ASP.NET Core 中的选项模式(Options)


参考文献:
asp.net core 中的选项模式