这篇博客是写给自己看的。已经不止一次看到AddOptions的出现,不管是在.net core源码还是别人的框架里面,都充斥着AddOptions。于是自己大概研究了下,没有深入,因为,我的功力还是不够,等能力到了再回头研究下。在这里还是要说一遍,因为DI的重要性不言而喻,不必谈的太深,说下自己的理解:
DI实现其实很简单,首先设计类来实现接口,而不是把所有的程序逻辑写在一个类文件中,然后我们传入一个接口和一个继承自接口的类作为参数,然后我们在相应的函数那将泛型参数T作为形参,伪代码:
//调用部分
HandleDI<ITest, Test>
//实现部分
HandleDI<TInterface, T>
// 使用反射,EMIT,委托来实例化T创建TInterface的对象
然后我们使用反射或者EMIT或是委托TInterface对象。这就是DI的实现过程。
DI说白了,作用就是 解耦的 实例化继承自接口的类
如果在程序中基于IOptions<TOptions>实现了你自己的选项配置类,最好就是调用AddOptions完成Options的几个重要对象的实例化。
AddOptions: 完成几个重要的Options对象的实例化:
代码语言:javascript复制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;
}
Configure: 完成的是TOption类的实例化过程,最终调用AddSingleton做DI。
代码语言:javascript复制/// <summary>
/// Registers an action used to configure a particular type of options.
/// Note: These are run before all <seealso cref="PostConfigure{TOptions}(IServiceCollection, Action{TOptions})"/>.
/// </summary>
/// <typeparam name="TOptions">The options type to be configured.</typeparam>
/// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
/// <param name="configureOptions">The action used to configure the options.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
=> services.Configure(Options.Options.DefaultName, configureOptions);
/// <summary>
/// Registers an action used to configure a particular type of options.
/// Note: These are run before all <seealso cref="PostConfigure{TOptions}(IServiceCollection, Action{TOptions})"/>.
/// </summary>
/// <typeparam name="TOptions">The options type to be configured.</typeparam>
/// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
/// <param name="name">The name of the options instance.</param>
/// <param name="configureOptions">The action used to configure the options.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions)
where TOptions : class
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (configureOptions == null)
{
throw new ArgumentNullException(nameof(configureOptions));
}
services.AddOptions();
services.AddSingleton<IConfigureOptions<TOptions>>(new ConfigureNamedOptions<TOptions>(name, configureOptions));
return services;
}
这两个的实现,都是IOC的功劳,如果不去深究其作用,单单就是看代码,其实就是DI的实例化接口类。
参考文章: ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor
.NET Core采用的全新配置系统[1]: 读取配置数据