在前面的文章中,我们介绍过将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方法,自己用多了,就更能理解了
以上,就是关于选项的一些小应用和总结。
更多分享,请大家关注我的个人公众号:
标签:选项,Core,positionOptions,ASP,string,options,NET,public,Configure From: https://www.cnblogs.com/fei686868/p/16888680.html