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;
        }
        
目录
相关文章
|
1月前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
48 5
|
2月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
50 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
1月前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
34 3
|
17天前
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
36 0
|
4月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
53 7
|
4月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
91 0
|
5月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
72 0
|
5月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
5月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
167 0
|
8月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
233 0