zoukankan      html  css  js  c++  java
  • asp.net core 系列 12 选项 TOptions

    一.概述

      本章讲的选项模式是对Configuration配置的功能扩展。 讲这篇时有个专用名词叫“选项类(TOptions)” 。该选项类作用是指:把选项类中的属性与配置来源中的键关联起来。举个例,假设json文件有个Option1键,选项类中也有个叫Option1的属性名,经过选项配置,这样就能把json中的键的值映射到选项类属性值中。也可以理解在项目应用中,把一个json文件序列化到.net类。

      1.1选项接口介绍

        在官方文档中选项接口有很多,这里列举了这些选项接口。所有选项接口基本都继承了TOptions接口。

        // Used for notifications when TOptions instances change
        public interface IOptionsMonitor<out TOptions>
        {
            //
            // 摘要:
            //     Returns the current TOptions instance with the Microsoft.Extensions.Options.Options.DefaultName.
            TOptions CurrentValue { get; }
            //...
        }
    
    
        // Used to create TOptions instances
        public interface IOptionsFactory<TOptions> where TOptions : class, new()
        {
            //
            // 摘要:
            //     Returns a configured TOptions instance with the given name.
            TOptions Create(string name);
        }
    
    
        // Represents something that configures the TOptions type. Note: These are run before all 
        public interface IConfigureOptions<in TOptions> where TOptions : class
        {
            //
            // 摘要:
            //     Invoked to configure a TOptions instance.
            //
            // 参数:
            //   options:
            //     The options instance to configure.
            void Configure(TOptions options);
        }
    
    
        public interface IPostConfigureOptions<in TOptions> where TOptions : class
        {
            //
            // 摘要:
            //     Invoked to configure a TOptions instance.
            //
            // 参数:
            //   name:
            //     The name of the options instance being configured.
            //
            //   options:
            //     The options instance to configured.
            void PostConfigure(string name, TOptions options);
        }
    
    
        public interface IConfigureNamedOptions<in TOptions> : IConfigureOptions<TOptions> where TOptions : class
        {
            //
            // 摘要:
            //     Invoked to configure a TOptions instance.
            //
            // 参数:
            //   name:
            //     The name of the options instance being configured.
            //
            //   options:
            //     The options instance to configure.
            void Configure(string name, TOptions options);
        }
    
    
        // Used by IOptionsMonitor<TOptions> to cache TOptions instances.
        public interface IOptionsMonitorCache<TOptions> where TOptions : class
        {
            //
            // 摘要:
            //     Clears all options instances from the cache.
            void Clear();
            //
            // 摘要:
            //     Gets a named options instance, or adds a new instance created with createOptions.
            //
            // 参数:
            //   name:
            //     The name of the options instance.
            //
            //   createOptions:
            //     The func used to create the new instance.
            //
            // 返回结果:
            //     The options instance.
            TOptions GetOrAdd(string name, Func<TOptions> createOptions);
            //
            // 摘要:
            //     Tries to adds a new option to the cache, will return false if the name already
            //     exists.
            //
            // 参数:
            //   name:
            //     The name of the options instance.
            //
            //   options:
            //     The options instance.
            //
            // 返回结果:
            //     Whether anything was added.
            bool TryAdd(string name, TOptions options);
            //
            // 摘要:
            //     Try to remove an options instance.
            //
            // 参数:
            //   name:
            //     The name of the options instance.
            //
            // 返回结果:
            //     Whether anything was removed.
            bool TryRemove(string name);
        }
    
    
        // Used to access the value of TOptions for the lifetime of a request
        public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions> where TOptions : class, new()
        {
            //
            // 摘要:
            //     Returns a configured TOptions instance with the given name.
            TOptions Get(string name);
        }
    
        //Used to retrieve configured TOptions instances
        public interface IOptions<out TOptions> where TOptions : class, new()
        {
            //
            // 摘要:
            //     The default configured TOptions instance
            TOptions Value { get; }
        }

         (1)  IOptionsMonitor<TOptions>

          IOptionsMonitor<TOptions>用于TOptions实例更改时的通知,用于管理 TOptions选项类 。该IOptionsMonitor<TOptions>支持以下方案:

          (1) 更改通知。当配置文件发生修改时,会监听同步到选项类。

          (2) 命名选项。IConfigureNamedOptions支持命名选项。接口继续关系 IConfigureNamedOptions:IConfigureOptions

          (3) 重新加载配置。通过 IOptionsSnapshot 重新加载配置数据,IOptionsMonitor也支持该功能。 接口继续关系IOptionsSnapshot :IOptions

          (4) 选择性选项失效 (IOptionsMonitorCache<TOptions>)。

         (2)  其它接口

          IOptionsFactory<TOptions> 负责产生TOptions选项实例,它具有单个 Create 方法。

          默认实现采用所有已注册 IConfigureOptions<TOptions> 和 IPostConfigureOptions<TOptions> 并首先运行所有配置(所有的来源配置),

          然后才进行选项后期配置IPostConfigureOptions<TOptions> 。

          IOptionsMonitorCache<TOptions>用于缓存TOptions实例。

    1.2 常规选项配置

      TOptions选项类必须为包含公共无参数构造函数的非抽象类。下面示例中选项类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添加到服务容器,并绑定到配置IConfiguration上
    //Registers a configuration instance which TOptions will bind against.
    services.Configure<MyOptions>(Configuration);
    private readonly MyOptions _options;
    //OtherPages/Page1
    public Page1Model( IOptionsMonitor<MyOptions> optionsAccessor)
    {
         _options = optionsAccessor.CurrentValue;
    }
         public void OnGet() {
         var option1 = _options.Option1;
         var option2 = _options.Option2;
         var  SimpleOptions = $"option1 = {option1}, option2 = {option2}";
    }
    
    //此时SimpleOptions值:"option1 = value1_from_ctor, option2 = 5"
    //下面在appsettings.json 文件添加 option1 和 option2 的值。
       "option1": "value1_from_json",
       "option2": -1,

           当配置文件appsettings.json中option1和option2键的值改变后,MyOptions 选项类中的属性option1和option2的值也会改变。 下面再次运行OtherPages/Page1

    //此时SimpleOptions的值为:"option1 = value1_from_json, option2 = -1"

      为什么MyOptions类中option1,option2会取到appsettings.json文件中的值呢?因为MyOptions选项类注入到Iconfiguration服务后与appsettings.json文件中键相同,形成了映射。

      1.3 通过委托配置简单选项

       使用委托设置选项值。 此示例应用使用 MyOptionsWithDelegateConfig 类 ,这里仍然是使用相同的键Option1,Option2。 它通过 MyOptionsWithDelegateConfig 使用委托来配置绑定。

    public class MyOptionsWithDelegateConfig
    {
        public MyOptionsWithDelegateConfig()
        {
           // Set default value.
           Option1 = "value1_from_ctor";
        }
        
         public string Option1 { get; set; }
         public int Option2 { get; set; } = 5;
    }
    services.Configure<MyOptions>(Configuration);
    //第二个注入服务
    services.Configure<MyOptionsWithDelegateConfig>(myOptions =>
    {
       // 在Page1Model构造方法中生成MyOptionsWithDelegateConfig实例时调用
         myOptions.Option1 = "value1_configured_by_delegate";
         myOptions.Option2 = 500;
    });
    public Page1Model(
                IConfiguration configuration,
                IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
                IOptionsMonitor<MyOptions> optionsAccessor
              )
            {
            
                _optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
                _options = optionsAccessor.CurrentValue;
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
            private readonly MyOptions _options;
            private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig;
    
            public string BindGUIDMsg { get; set; }
    
            public void OnGet()
            {
                BindGUIDMsg = $"option1 = {_options.Option1}, option2 = {_options.Option2}";
    
                BindGUIDMsg += "</br>";
    
                BindGUIDMsg += $"delegate_option1 = {_optionsWithDelegateConfig.Option1}, " +
                               $"delegate_option2 = {_optionsWithDelegateConfig.Option2}";
            }

      每次调用 Configure 都会将 IConfigureOptions<TOptions> 服务添加到服务容器。 在前面的示例中,Option1 和 Option2 的值同时在 appsettings.json 中指定,但 Option1 和 Option2 的值被配置的委托替代。

      当启用多个配置服务时,指定的最后一个配置源优于其他源,由其设置配置值。 运行应用时,页面模型的 OnGet 方法返回显示选项类值的字符串:

    // myOptions实例取值如下:
    SimpleOptions:option1 = -1,option2 = 5 
    // MyOptionsWithDelegateConfig实例取值如下:
    delegate_option1 = value1_configured_by_delegate,delegate_option2 = 500

       1.4 子选项配置

       当配置文件中的子节点需要与选项类进行关联映射时,可以通过服务注入bind到指定的Configuration节点。在以下代码中,已向服务容器添加第三个 IConfigureOptions<TOptions> 服务。 它将 MySubOptions 绑定到 appsettings.json 文件的 subsection 部分:

    "Option1": "value1_from_json",
          "Option2": -1,
          "subsection": {
             "suboption1": "subvalue1_from_json",
             "suboption2": 200
          }
    public class MySubOptions
    {
         public MySubOptions()
         {
              // Set default values.
              SubOption1 = "value1_from_ctor";
              SubOption2 = 5;
         }
    
         public string SubOption1 { get; set; }
         public int SubOption2 { get; set; }
    }
    //第三个IConfigureOptions<TOptions>注入服务
    services.Configure<MySubOptions>(Configuration.GetSection("subsection"));
    //OtherPages/Page1              
    public Page1Model(
           IConfiguration configuration,
           IOptionsMonitor<MyOptionsWithDelegateConfig> optionsAccessorWithDelegateConfig,
           IOptionsMonitor<MyOptions> optionsAccessor,
           IOptionsMonitor<MySubOptions> subOptionsAccessor
       )
       {
            
           _optionsWithDelegateConfig = optionsAccessorWithDelegateConfig.CurrentValue;
           _options = optionsAccessor.CurrentValue;
           _subOptions = subOptionsAccessor.CurrentValue;
                Configuration = configuration;
       }
    
    public IConfiguration Configuration { get; }
    private readonly MyOptions _options;
    private readonly MyOptionsWithDelegateConfig _optionsWithDelegateConfig;
    private readonly MySubOptions _subOptions;
    // OnGet方法
    SubOptions = $"subOption1 = {_subOptions.SubOption1}, subOption2 = {_subOptions.SubOption2}"
    
    
    //运行应用时,OnGet 方法返回显示子选项类值的字符串:
    // MySubOptions实例取值如下:
    subOption1 = subvalue1_from_json,subOption2 = 200

      1.5 IConfigureNamedOptions选项命名

      IConfigureNamedOptions:是用于对选项类在注入服务时,进行命名。下面是把MyOptions选项类注入到服务,并取了别名named_options_1。 如下所示:

    services.Configure<MyOptions>("named_options_1", Configuration);
    //在要使用的页面,如下所示:
    private readonly MyOptions _named_options_1;
    public IndexModel(IOptionsSnapshot<MyOptions> namedOptionsAccessor)
    {
        _named_options_1 = namedOptionsAccessor.Get("named_options_1");
    }
    // IOptionsSnapshot源码
    public interface IOptionsSnapshot<out TOptions> : IOptions<TOptions> where TOptions : class, new()
    {
        //
        // 摘要:
        //     Returns a configured TOptions instance with the given name.
        TOptions Get(string name);
    }

      1.6 ConfigureAll 

      上面介绍的选项类,在注入服务时都是使用的services.Configure,它是针对选项类的当前实例,例如:在page1和page2都使用了实例MyOptions( private readonly MyOptions _options)但它们属于不同的实例。

    //使用 ConfigureAll 方法配置所有选项实例
    services.ConfigureAll<MyOptions>(myOptions =>
    {
         //所有MyOptions实例配置 Option1的值
         myOptions.Option1 = "ConfigureAll replacement value";
    });

      总结:

           选项模式是对Configuration配置的功能扩展,主要用于把json文件序列化到.net类(选项类)。通过注入services. Configure或services.ConfigureAll把选项类注入到服务并绑定到Configuration上。 选项这篇还有其它功能如:选项后期配置( IPostConfigureOptions), 启动期间访问选项, 选项验证等,详细了解查看官网。

    参考文献

    官方资料:asp.net core 选项

    欢迎添加个人微信号:Like若所思。

    欢迎关注我的公众号,不仅为你推荐最新的博文,还有更多惊喜和资源在等着你!一起学习共同进步!

  • 相关阅读:
    MySql 有用的函数
    mysql 触发器
    java之switch语句
    MaxAlertView 强大的弹框试图
    AVMoviePlayer 视频播放器
    Mac下不能安装第三方下载软件
    HTTPS链式编程——AFNetworking 3.0
    iOS推送证书生成pem文件(详细步骤)
    iOS成长之路-使用系统默认声音、震动
    iOS 怎么自定制推送声音呢?(APP运行时和APP进入后台时)
  • 原文地址:https://www.cnblogs.com/cool2feel/p/11526030.html
Copyright © 2011-2022 走看看