在前面的文章中,我们介绍过将appsetting等配置文件映射到实体的的方式
https://www.cnblogs.com/fei686868/p/16779249.html

这里呢,我们介绍关于选项的另一种用法,就是通过IOptions等选项来使用。

他们的区别呢,以前那种是只实现映射,如果要注入,需要自己写注入代码;但使用IOptions等方式呢,是自动注入了,我们无需再写注入代码,

显得更简洁,同时呢,扩展性更强。

本文示例环境:netcore3.1

为了演示代码,我们在appsetting.json中新增一个配置和实体

  "Position": {
    "Title": "这个是标题",
    "Name": "这个是名称"
  }
    public class PositionOptions
    {
        public const string Position = "Position"; //定义节点名称,与配置对应。这边定义只是为了方便管理,不用到处写字符串

        public string Title { get; set; }
        public string Name { get; set; }
    }

我们先看个简单的写法:

 services.Configure<实体名称>(Configuration.GetSection("配置文件中的节点名称"));

这里我们采用的是services自带的Configure<>方法进行处理。

下面上实际代码:

Startup.cs中配置

      public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<PositionOptions>(Configuration.GetSection(PositionOptions.Position)); //映射和注入
           
        }

应用:

    public class PositionController : Controller
    {
        private readonly PositionOptions _positionOptions;
        public PositionController(IOptions<PositionOptions> options) //通过IOption实现注入
        {
            _positionOptions = options.Value;  //获取对应的Value即可
        }
        public IActionResult Index()
        {
            string str = _positionOptions.Name; //这边就能获取到配置的Name了

            return View();
        }
    }

 

上面我们采用IOptions对象来处理,该方式呢,有个注意点:
不会读取在应用启动后对 JSON 配置文件所做的更改

就是启动时读取而已,如果配置文件改了,不会热重载。但是在现实中,我们该配置,那还真会有。咋整?

选项有3种接口模式:

1、IOptions<TOptions>
  不支持热重载

  不支持命名选项(下面会讲什么是命名选项)

  注册为单一实例且可以注入到任何服务生存期

2、IOptionsSnapshot<TOptions>

   支持热重载,就是配置文件修改后,会更新。

   注册为Scope类型,因此无法注入到单一实例服务

   支持命名选项

3、IOptionsMonitor<TOptions>

    用于检索选项并管理 TOptions 实例的选项通知

    注册为单一实例且可以注入到任何服务生存期。

    支持更改通知、命名选项、热重载

 

不管用什么方式,不影响Startup.cs中服务注入的Configure 方法的写法。

对于日常项目应用来说,主要就是热重载的区别。不同方式,性能影响也不太一样。虽然有时候可以忽略性能差异。

有些配置是启动后,就不需要再修改的,可以采用IOptions。否则,请使用后面两种。

但相对来说,第3种更适合一点。

我们看看写法

IOptionsSnapshot 写法

    public class PositionController : Controller
    {
        private readonly PositionOptions _positionOptions;
        public PositionController(IOptionsSnapshot<PositionOptions> options) //通过IOption实现注入
        {
            _positionOptions = options.Value;  //获取对应的Value即可
        }
        public IActionResult Index()
        {
            string str = _positionOptions.Name; //这边就能获取到配置的Name了

            return View();
        }
    }

IOptionsMonitor 写法

    public class PositionController : Controller
    {
        private readonly PositionOptions _positionOptions;
        public PositionController(IOptionsMonitor<PositionOptions> options) //通过IOption实现注入
        {
            _positionOptions = options.CurrentValue;  //获取对应的Value即可
        }
        public IActionResult Index()
        {
            string str = _positionOptions.Name; //这边就能获取到配置的Name了

            return View();
        }
    }

三者,写法基本相同。

那我们先做个小总结
1、IOptions ,注册为单例,不支持热重载。
2、IOptionsSnapshot,注册为Scope范围,支持热重载

3、IOptionsMonitor,注册为单例,支持热重载。

下面我们再介绍下命名选项的情况,仅 IOptionsSnapshot和IOptionsMonitor 二者支持

我们换个例子,改下配置

{ 
"班级情况": {
    "1班": {
      "StudentCount": 50,
      "AvgScore": 80
    },
    "2班": {
      "StudentCount":60,
      "AvgScore": 90
    }
  }
}

加入配置是这样的,那我们需要分别获取1班和2班的学生数和平均分,怎么获取?

我们分析这种情况,出现了同层级,key名称不一样(1班,2班,这就是命名选项,同层级,不同key),而每个key对象的子内容是里面是格式是一样的。

我们就这么写,定义实体

    public class ClassData
    {
 public const string NodeName = "班级情况";
public const string ClasName1 = "1班"; public const string ClassName2 = "2班"; public int StudentCount { get; set; } public int AvgScore { get; set; } }

实体中,我们定义了两个变量与节点一一对应

注入的时候是有变化的

   services.Configure<ClassData>( ClassData.ClassName1,Configuration.GetSection("班级情况:1班"));
            services.Configure<ClassData>(ClassData.ClassName2, Configuration.GetSection("班级情况:2班"));

看到了没,得写2个,分别写。实体类型都一样,但是 Configure方法的name参数不一样。

应用端:

 private readonly ClassData _classData1;//1班
        private readonly ClassData _classData2;//2班
        public PositionController(IOptionsSnapshot<ClassData> options) //通过IOption实现注入
        {
            _classData1 = options.Get(ClassData.ClassName1); //分别获取定义的name对应的数据
            _classData2 = options.Get(ClassData.ClassName2);
        }

再获取数据时,需要用这种方式来获取。

看起来是一小点的知识,其实在很多组件封装上很实用。比如Abp就很多Configure方法,自己用多了,就更能理解了

以上,就是关于选项的一些小应用和总结。

 

原文地址:http://www.cnblogs.com/fei686868/p/16888680.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性