加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

详解ASP.NET Core3.0 配置的Options模式

发布时间:2020-08-21 13:35:43 所属栏目:编程 来源:网络整理
导读:这篇文章主要介绍了详解ASP.NET Core3.0 配置的Options模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面

总结:IOptions和IOptionsMonitor两种方式采用了Singleton模式,但区别在于IOptionsMonitor会监控对应数据源的变化,如果发生了变化则更新实例的配置值,但不会重新提供新的实例。IOptionsSnapshot方式采用了Scoped模式每次请求采用同一个实例,在下一次请求的时候获取到的是一个新的实例,所以如果数据源发生了改变,会读取到新的值。先大概记一下这一的情况,在下文剖析IOptions的内部处理机制的时候就会明白为什么会这样。

4.数据更新提醒

IOptionsMonitor方式还提供了一个OnChange方法,当数据源发生改变的时候会触发它,所以如果想在这时候做点什么,可以利用这个方法实现。示例代码:

_optionsMonitor.OnChange((theme,name)=> { Console.WriteLine(theme.Name +"-"+ name); });

5.不采用Configuration配置作为数据源的方式

上面的例子都是采用了读取配置的方式,实际上Options模式和上一章的Configuration配置方式使分开的,读取配置只不过是Options模式的一种实现方式,例如可以不使用Configuration中的数据,直接通过如下代码注册:

services.Configure<Theme>("ThemeBlack", theme => { theme.Color = "#000000"; theme.Name = "Black"; });

6.ConfigureAll方法

系统提供了一个ConfigureAll方法,可以将所有对应的实例统一设置。例如如下代码:

services.ConfigureAll<Theme>(theme => { theme.Color = "#000000"; theme.Name = "Black2"; });

此时无论通过什么名称去获取Theme的实例,包括不存在对应设置的名称,获取到的值都是本次通过ConfigureAll设置的值。

7.PostConfigure和PostConfigureAll方法

这两个方法和Configure、ConfigureAll方法类似,只是它们会在Configure、ConfigureAll之后执行。

8.多个Configure、ConfigureAll、PostConfigure和PostConfigureAll的执行顺序

可以这样理解,每个Configure都是去修改一个名为其设置的名称的变量,以如下代码为例:

services.Configure<Theme>("ThemeBlack", theme => { theme.Color = "#000000"; theme.Name = "Black"; });

这条设置就是去修改(注意是修改而不是替换)一个名为"ThemeBlack"的Theme类型的变量,如果该变量不存在,则创建一个Theme实例并赋值。这样就生成了一些变量名为“空字符串、“ThemeBlue”、“ThemeBlack”的变量(只是举例,忽略空字符串作为变量名不合法的顾虑)”。

依次按照代码的顺序执行,这时候如果后面的代码中出现同名的Configure,则修改对应名称的变量的值。如果是ConfigureAll方法,则修改所有类型为Theme的变量的值。

而PostConfigure和PostConfigureAll则在Configure和ConfigureAll之后执行,即使Configure的代码写在了PostConfigure之后也是一样。

至于为什么会是这样的规则,下一节会详细介绍。

二、内部处理机制解析
1. 系统启动阶段,依赖注入

上一节的例子中涉及到了三个接口IOptions、IOptionsSnapshot和IOptionsMonitor,那么就从这三个接口说起。既然Options模式是通过这三个接口的泛型方式注入提供服务的,那么在这之前系统就需要将它们对应的实现注入到依赖注入容器中。这发生在系统启动阶段创建IHost的时候,这时候HostBuilder的Build方法中调用了一个services.AddOptions()方法,这个方法定义在OptionsServiceCollectionExtensions中,代码如下:

public static class OptionsServiceCollectionExtensions { public static IServiceCollection AddOptions(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>))); services.TryAdd(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsManager<>))); services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>))); services.TryAdd(ServiceDescriptor.Transient(typeof(IOptionsFactory<>), typeof(OptionsFactory<>))); services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>))); return services; } public static IServiceCollection Configure<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class => services.Configure(Options.Options.DefaultName, configureOptions); public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions) where TOptions : class { //省略非空验证代码 services.AddOptions(); services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, configureOptions)); return services; } public static IServiceCollection ConfigureAll<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class => services.Configure(name: null, configureOptions: configureOptions); //省略部分代码 }

可见这个AddOptions方法的作用就是进行服务注入,IOptions<>、IOptionsSnapshot<>对应的实现是OptionsManager<>,只是分别采用了Singleton和Scoped两种生命周期模式,IOptionsMonitor<>对应的实现是OptionsMonitor<>,同样为Singleton模式,这也验证了上一节例子中的猜想。除了上面提到的三个接口外,还有IOptionsFactory<>和IOptionsMonitorCache<>两个接口,这也是Options模式中非常重要的两个组成部分,接下来的内容中会用到。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读