ASP.NET Core 选项模式源码学习Options Configure(一)
2019-12-11 09:06
1101 查看
前言
ASP.NET Core 后我们的配置变得更加轻量级了,在ASP.NET Core中,配置模型得到了显著的扩展和增强,应用程序配置可以存储在多环境变量配置中,appsettings.json用户机密等 并可以通过应用程序中的相同界面轻松访问,除此之外,ASP.NET中的新配置系统允许使用Options的强类型设置。
强类型Options
在ASP.NET Core中没有AppSettings["Key"]默认方法,那么推荐的是创建强类型的配置类,去绑定配置项。
public class MyOptions { public string Name { get; set; } public string Url { get; set; } }
然后我们在appsettings.json中添加如下内容:
{ "MyOptions": { "Name": "TestName", "Url": "TestUrl" } }
配置绑定到类
ConfigureServices方法进行配置以绑定到类
public void ConfigureServices(IServiceCollection services) { services.Configure<MyOptions>(Configuration.GetSection("MyOptions")); services.AddControllers(); }
MyOptions只需将IOptions<>类的实例注入控制器中,然后通过Value属性获取Myoptions:
public class WeatherForecastController : ControllerBase { private readonly MyOptions _options; public WeatherForecastController(IOptions<MyOptions> options) { _options = options.Value; } [HttpGet] public OkObjectResult Get() { return Ok(string.Format("Name:{0},Url:{1}", _options.Name,_options.Url)); } }
Configure
委托配置
//基础注册方式 services.Configure<MyOptions>(o => { o.Url = "MyOptions"; o.Name = "Name111"; }); //指定具体名称 services.Configure<MyOptions>("Option", o => { o.Url = "MyOptions"; o.Name = "Name111"; }) ; //配置所有实例 services.ConfigureAll<MyOptions>(options =>{ options.Name = "Name1"; options.Url = "Url1";});
通过配置文件配置
// 使用配置文件来注册实例 services.Configure<MyOptions>(Configuration.GetSection("MyOptions")); // 指定具体名称 services.Configure<MyOptions>("Option", Configuration.GetSection("MyOptions"));
PostConfigure
PostConfigure会在Configure注册完之后再进行注册
services.PostConfigure<MyOptions>(o => o.Name = "Name1"); services.PostConfigure<MyOptions>("Option", o => o.Name = "Name1"); services.PostConfigureAll<MyOptions>(o => o.Name = "Name1");
源码解析
IConfigureOptions接口
public interface IConfigureOptions<in TOptions> where TOptions : class { void Configure(TOptions options); }
Configure为方便使用IConfigureOptions注册单例ConfigureNamedOptions
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; }
上面代码IConfigureOptions实现了ConfigureNamedOptions,那我们再来看看内部源码
ConfigureNamedOptions 其实就是把我们注册的Action包装成统一的Configure方法,以方便后续创建Options实例时,进行初始化。
public class ConfigureNamedOptions<TOptions> : IConfigureNamedOptions<TOptions> where TOptions : class { public ConfigureNamedOptions(string name, Action<TOptions> action) { Name = name; Action = action; } public string Name { get; } public Action<TOptions> Action { get; } public virtual void Configure(string name, TOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } // Null name is used to configure all named options. if (Name == null || name == Name) { Action?.Invoke(options); } } public void Configure(TOptions options) => Configure(Options.DefaultName, options);}
在 services.Configure(Configuration.GetSection("MyOptions")); 我们不指定具体名称的时候默认是如下代码片段
public virtual void Configure(string name, TOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } // Null name is used to configure all named options. if (Name == null || name == Name) { Action?.Invoke(options); } } public void Configure(TOptions options) => Configure(Options.DefaultName, options);
默认使用的是Options.DefaultName
AddOptions默认方法默认为我们注册了一些核心的类
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; }
相关文章推荐
- ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
- ASP.NET Core 2.1 源码学习之 Options[1]:Configure
- ASP.NET Core 2.1 源码学习之 Options[2]:IOptions
- ASP.NET Core 源码学习之 Logging[2]:Configure
- ASP.NET Core 源码学习之 Options[2]:IOptions
- ASP.NET Core 源码学习之 Logging[1]:Introduction
- ASP.NET Core 源码学习之 Logging[2]:Configure
- ASP.NET Core 源码学习之Logging[1]:Introduction
- (13)ASP.NET Core 中的选项模式(Options)
- ASP.NET Core 2.1 源码学习之 Options[3]:IOptionsMonitor
- ASP.NET Core 源码学习之 Options[1]:Configure
- 【ASP.NET Core 】ASP.NET Core 源码学习之 Logging[1]:Introduction
- ASP.NET Core 源码学习之 Logging[3]:Logger
- ASP.NET Core 源码学习之 Logging[4]:FileProvider
- ASP.NET Core 源码学习之 Options[3]:IOptionsSnapshot
- Asp.Net Core + Dapper + Repository 模式 + TDD 学习笔记
- ASP.NET Core 2.2 基础知识(七) 选项模式
- DotText源码学习——ASP.NET的工作机制
- ASP.NET Core MVC 源码学习:详解 Action 的匹配
- asp.net学习之ado.net(无连接模式中的DataAdapter)