ASP.NET Core 选项模式源码学习Options Configure(一)

前言

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;
        }
        

原文地址:https://www.cnblogs.com/yyfh/p/12020522.html

时间: 2024-11-05 15:55:17

ASP.NET Core 选项模式源码学习Options Configure(一)的相关文章

ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)

前言 IOptionsMonitor 是一种单一示例服务,可随时检索当前选项值,这在单一实例依赖项中尤其有用.IOptionsMonitor用于检索选项并管理TOption实例的选项通知, IOptionsMonitor 支持以下方案: 更改通知 命名选项 可重载配置 选择性选项失效 (IOptionsMonitorCache) IOptionsMonitor public interface IOptionsMonitor<out TOptions> { /// <summary>

ASP.NET Core 选项模式源码学习Options IOptions(二)

前言 上一篇文章介绍IOptions的注册,本章我们继续往下看 IOptions IOptions是一个接口里面只有一个Values属性,该接口通过OptionsManager实现 public interface IOptions<out TOptions> where TOptions : class, new() { /// <summary> /// The default configured <typeparamref name="TOptions&qu

asp.net core 3.1 源码学习(二)

IWebHost实现类WebHost internal class WebHost : IWebHost, IAsyncDisposable { private static readonly string DeprecatedServerUrlsKey = "server.urls"; private readonly IServiceCollection _applicationServiceCollection; private IStartup _startup; privat

asp.net core 3.1 源码学习 http相关

一.IFeatureCollection 表示Http特性的集合,该集合存放一些http相关特性,如IHttpRequestFeature.IHttpResponseFeature 当构建HttpContext.HttpRequest.HttpResponse对象时,会从这些特性里面解析构建对应的类 public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>> { /// <summ

jquery源码学习(一)core部分

这一部分是jquery的核心 jquery的构造器 jquery的核心工具函数 构造器 jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQu

Redis源码学习-Lua脚本

Redis源码学习-Lua脚本 1.Sublime Text配置 我是在Win7下,用Sublime Text + Cygwin开发的,配置方法请参考<Sublime Text 3下C/C++开发环境搭建>. 要注意的是:在Cygwin中安装Lua解析器后,SublimeClang插件就能识别出可饮用的Lua头文件了,因为Build System中我们已经配置过"-I", "D:\\cygwin64\\usr\\include",而新安装的Lua头文件会

jQuery源码学习笔记:扩展工具函数

// 扩展工具函数 jQuery.extend({ // http://www.w3school.com.cn/jquery/core_noconflict.asp // 释放$的 jQuery 控制权 // 许多 JavaScript 库使用 $ 作为函数或变量名,jQuery 也一样. // 在 jQuery 中,$ 仅仅是 jQuery 的别名,因此即使不使用 $ 也能保证所有功能性. // 假如我们需要使用 jQuery 之外的另一 JavaScript 库,我们可以通过调用 $.noC

FireMonkey 源码学习(5)

(5)UpdateCharRec 该函数的源码分析如下: procedure TTextLayoutNG.UpdateCharRec(const ACanvas: TCanvas; NeedBitmap: Boolean; var NewRec: PCharRec; HasItem: Boolean; const CharDic: TCharDic; const AFont: TFont; const Ch: UCS4Char; const NeedPath: Boolean = False);

jquery源码学习

jQuery 源码学习是对js的能力提升很有帮助的一个方法,废话不说,我们来开始学习啦 我们学习的源码是jquery-2.0.3已经不支持IE6,7,8了,因为可以少学很多hack和兼容的方法. jquery-2.0.3的代码结构如下 首先最外层为一个闭包, 代码执行的最后一句为window.$ = window.jquery = jquery 让闭包中的变量暴露倒全局中. 传参传入window是为了便于压缩 传入undefined是为了undifined被修改,他是window的属性,可以被修