ASP.NET Core 框架基础 - 配置系统 Options 模式
参考资料:
- Options pattern in ASP.NET Core
- http://www.cnblogs.com/artech/p/new-config-system-01.html
- Options Github Source
本文大纲:
Options 模式
在真实的项目中我们大多采用 Options
模式来使用配置,Options
是配置的逻辑结构在对象层面的体现,通常,可以将一个 Configuration
对象绑定为一个 Options
对象。这样的绑定称为「配置绑定」。
配置绑定
Microsoft.Extensions.Configuration.Binder
包为 IConfiguration
接口定义了 Bind
扩展方法,该方法接收一个代表 Options
的 object
类型的参数,并将 Configuration
的配置数据绑定到该对象上。
1 | public static class ConfigurationBinder |
配置绑定的目标类型可以是一个简单的基元类型,也可以是一个自定义数据类型,还可以是一个数组、集合或者字典类型。上述 Bind
方法在进行配置绑定的过程中会根据不同的目标类型采用不同的策略。
Options
模式是对依赖注入的应用,通过调用 IServiceCollection
扩展方法 AddOptions
添加 Options
模式的服务注册,再通过 Configure<TOptions>
扩展方法配置目标 Options
的 T 类型。消费方利用 ServiceProvider
得到一个类型为 IOptions<TOptions>
的服务对象后,读取 Value
属性得到由配置绑定生成的 TOptions
实例。
1 | IConfiguration config = ...; |
扩展方法 AddOptions
当调用 IServiceCollection
的 AddOptions
时,该方法对 IOptions<>
接口注册一个服务,该服务的实现类型为 OptionsManager<TOptions>
,生命周期为 Singleton
。配置绑定生成的 Options
对象最终都是通过 OptionsManager<TOptions>
创建的。
1 | public static IServiceCollection AddOptions(this IServiceCollection services) |
以下是几个相关类型的定义:
OptionsManager
1 | public class OptionsManager<TOptions> : IOptions<TOptions> where TOptions: class, new() |
OptionsManager<TOptions>
类型的构造函数接受一个 IConfigureOptions<TOptions>
的集合,Options
对象的创建体现在 Value
属性上。该属性的实现非常简单,它先调用 TOptions
类型的默认无参构造函数(TOptions
代表的类型必须具有一个默认无参构造函数)创建一个空的 TOptions
对象,然后将其传递给构造函数中指定的ConfigureOptions<TOptions>
对象逐个进行转换处理。
IConfigureOptions
1 | public interface IConfigureOptions<in TOptions> where TOptions: class |
IConfigureOptions<TOptions>
接口定义了一个唯一的 Configure
方法,该方法将 Options
对象作为输入参数。
ConfigureOptions
1 | public class ConfigureOptions<TOptions>: IConfigureOptions<TOptions> where TOptions : class, new() |
IConfigure<TOptions>
的默认实现类型 ConfigureOptions<TOptions>
在其构造函数中接收一个 Action<TOptions>
委托对象,再在 Configure
方法中调用该委托实现对 TOptions
的操作。
扩展方法 Configure
1 | public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, IConfiguration config, Action<BinderOptions> configureBinder) |
在调用 IServiceCollection
的 Configure
方法时,其内部注册了一个 IConfigureOptions<TOptions>
接口的单例服务,其实际类型为 NamedConfigureFromConfigurationOptions<TOptions>
,该类型最终继承自 ConfigureOptions<TOptions>
类型,并且在其构造函数中声明了一个匿名方法作为 Action<TOptions>
的参数传入 NamedConfigureFromConfigurationOptions<TOptions>
中,最终实现配置绑定。
1 | public NamedConfigureFromConfigurationOptions(string name, IConfiguration config, Action<BinderOptions> configureBinder) |
创建 Options 对象
Options 编程模式以两个注册到 ServiceCollection
的服务为核心,这两个服务对应的服务接口分别是:
IOptions<TOptions>
: 直接提供最终绑定了配置数据的Options
对象IConfigureOptions<TOptions>
: 在Options
对象返回之前对它实施相应的初始化工作。
这个两个服务分别通过扩展方法 AddOptions
和 Configure
方法注册到指定的 ServiceCollection
中,服务的真实类型分别是 OptionsManager<TOptions>
和 NamedConfigureFromConfigurationOptions<TOptions>
,后者派生于 ConfigureOptions<TOptions>
。下图所示的 UML 体现了 Options
模型中涉及的这些接口/类型以及它们之间的关系。