【NET】.NET基础篇-5.启动流程之Configuration

上文书说到了WebApplicationBuilder,以及4个步骤的第一步-CreateBuilder。本文按照5个对象4个步骤的顺序继续往下讲,至于WebApplication后续还会出现,届时再详细介绍。

当前步骤:

var builder = WebApplication.CreateBuilder(args);builder.Configuration.XXX();

在这里插入图片描述

1.干啥的

1.1 真身

在.NET中,Configuration(配置)是一个用于管理应用程序设置的对象。它允许从多种异构数据源(如Json文件、环境变量、命令行参数,自定义配置源等)读取配置信息,并提供统一的API来访问这些配置,说白了,它的作用就是读取配置,然后再吐出这些配置给逻辑代码使用的。
在.NET8中,配置对象Configuration的核心是IConfiguration接口,而WebApplication.CreateBuilder(args)方法会初始化一个ConfigurationManager,它实现了IConfigurationBuilder和IConfiguration接口,用于构建和存储配置。dotnet源码:WebApplication.CreateBuilder()创建了ConfigurationManager
在这里插入图片描述
而我们使用的builder.Configuration其实就是ConfigurationManager

在这里插入图片描述
ConfigurationManager的源码在dotnet/runtime中,命名空间:Microsoft.Extensions.Configuration
在这里插入图片描述
而IConfigurationManager继承自IConfigurationBuilder和IConfiguration
在这里插入图片描述
– 严丝合缝
记忆:
builder.Configuration(dotnet中) ->
ConfigurationManager(runtime中)->
IConfigurationManager(runtime中) ->
IConfigurationBuilder&IConfiguration(runtime中)

1.2 作用

Configuration 是 .NET 中的应用程序配置管理系统,它负责:

  • 管理应用程序的所有配置信息,怎么管理?统一管理呗;
  • 支持多种异构配置源(文件、环境变量、数据库、Azure keyvault等);
  • 支持配置热更新和变更通知;

1.3 祛魅

Configuration 就是.NET中,程序自动读取你指定的配置信息,然后再给你提供几个方法,在程序中任意地方获取它读取到的配置,供你的逻辑代码使用。就像你,先喝水(读取配置信息),溜达到某个地方,放水(输出配置信息)。

2. 怎么用

先-配置
再-读

2.1 配置

2.1.1 多环境配置

配置源的加载顺序决定了优先级,后加载的配置源会覆盖先加载的同键值,默认顺序如下:

  1. appsettings.json
    • .AddJsonFile(文件名,文件是否可选加载,是否热加载);
  2. appsettings.{Environment}.json
    • 用于配置特定环境,如prod,dev,test
    • AddJsonFile(文件名,文件是否可选加载,是否热加载);
  3. 用户机密(仅开发环境)
    • builder.Configuration.AddUserSecrets();
  4. 环境变量
    • builder.Configuration.AddEnvironmentVariables(“MYPP_”);
  5. 命令行参数
    • builder.Configuration.AddCommandLine(args);
  6. 自定义配置源
    • builder.Configuration.AddCustomConfiguration();

源码中,在WebApplication.CreateBuilder()中,初始化ConfigurationManager时已经默认添加了配置源,喏:
在这里插入图片描述
当然,你也必须可以手动添加,也是我们当前知识点的主线任务之一

//Configurationbuilder.Configuration     
//基础文件配置    
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)     
//特定环境配置    
.AddJsonFile($"appsettins.{builder.Environment.EnvironmentName}.json", optional: false, reloadOnChange: true)     //环境变量配置    
.AddEnvironmentVariables("MYAPP_")     
//命令行配置    
.AddCommandLine(args);     
//用户自定义源配置    
.AddCustomConfigurtion()    
//用户机密配置,仅限于开发环境
if (builder.Environment.IsDevelopment()){
    builder.Configuration.AddUserSecrets<Program>();
 }

2.1.2 appsettings.json

appsettings.json和appsettings.{Environment}.json用法比较简单,不再细说。当然,除了json以外还可以添加xml和INI:

  • AddXmlFile()
  • AddIniFile()

2.1.3 用户机密

AddUserSecrets此方法通常只在开发环境中使用,在开发过程中安全存储敏感数据(如连接字符串,API密钥等)。避免将敏感信息提交到源代码仓库。
创建用户机密只需右键项目->管理用户机密。或者在Program.cs同级目录下secret.json中修改。

2.1.4 环境变量 AddEnvironmentVariables

这个方法可以将带有特定前缀的环境变量添加到配置中,如MYAPP_,并在添加到配置中后,去掉特定前缀。如设置环境变量MYAPP_ConnectionString,则在配置中可以通过键ConnectionString获取。
使用场景:

  • 容器化部署(Docker, Kubernetes)
  • 云服务平台(Azure, AWS, GCP)
  • CI/CD流水线配置
  • 不同环境(开发、测试、生产)的配置隔离

2.1.5 命令行

AddCommandLine添加命令行参数到配置系统中。允许在启动应用程序时通过命令行参数来覆盖其他配置源的设置。常用于调试或者某些自动化的脚本中。如启动时输入命令:
// 运行应用时传入参数:
// dotnet run --urls=“https://localhost:7000” --Environment=“Staging” --Logging:LogLevel:Default=“Debug”

2.1.6 自定义配置源 AddCustomConfiguration

自定义一个配置源,加载一个自定义的字典:
实现IConfigurationSource接口(以上配置源都对应一个souce,都是基于这个接口来实现的):

using Microsoft.Extensions.Configuration;
public class CustomConfigurationSource : IConfigurationSource{    
private readonly Dictionary<string, string> _data;    
public CustomConfigurationSource(Dictionary<string, string> data)   
 {       
 	 _data = data;    
 }    
public IConfigurationProvider Build(IConfigurationBuilder builder)    {        
		return new CustomConfigurationProvider(_data);    
}}

返回实现了IConfigurationProvider的提供程序:

using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
public class CustomConfigurationProvider : ConfigurationProvider
{    
private readonly Dictionary<string, string> _data;    
public CustomConfigurationProvider(Dictionary<string, string> data)    
{        
	_data = data;    
}    
public override void Load()    
{        
	// 将内存中的数据加载到配置中        
	foreach (var item in _data)        
	{           
	 	Data[item.Key] = item.Value;        
	 }    
 }}

扩展下IConfigurationBuilder接口,起个看起来像样子的名字:

public static class CustomConfigurationExtensions
{    
	public static IConfigurationBuilder AddCustomConfiguration(this IConfigurationBuilder builder, Dictionary<string, string> data)    
	{        
		return builder.Add(new CustomConfigurationSource(data));    
		}
}

使用自定义源

var builder = WebApplication.CreateBuilder(args);
// 添加其他配置源...
// 自定义配置源
var customConfig = new Dictionary<string, string>{    ["Custom:Key1"] = "Value1",    ["Custom:Key2"] = "Value2"};builder.Configuration.AddCustomConfiguration(customConfig);

2.2 读

2.2.1.直接读 builder.Configuration[]

- 简单读取
- 分层键读取(冒号分割)
var builder = WebApplication.CreateBuilder(args);
// 简单键值读取
var appName = builder.Configuration["Application:Name"];var version = builder.Configuration["Application:Version"];
// 分层键读取(冒号分隔)
var connectionString = builder.Configuration["Database:ConnectionStrings:Default"];var logLevel = builder.Configuration["Logging:LogLevel:Default"];

2.2.2 节点读 GetSection

很显然,除了GetSection,还有GetChildren

var builder = WebApplication.CreateBuilder(args);
// 获取配置节
var databaseSection = builder.Configuration.GetSection("Database");var connectionString = databaseSection["ConnectionString"];
var timeout = databaseSection["Timeout"];
// 遍历配置节
var loggingSection = builder.Configuration.GetSection("Logging:LogLevel");
foreach (var child in loggingSection.GetChildren())
{    
	Console.WriteLine($"{child.Key}: {child.Value}");
}

2.2.3 强类型绑定 POCO

public class DatabaseOptions
{    
public string ConnectionString { get; set; } = string.Empty;    
public int Timeout { get; set; } = 30;    
public bool EnableRetry { get; set; } = true;}
public class ApplicationOptions
{    
public string Name { get; set; } = string.Empty;    
public string Version { get; set; } = string.Empty;    
public List<string> SupportedCultures { get; set; } = new();
}
  • 直接绑定 GetSection().Bind(object)
// 方式1:直接绑定
var dbOptions = new DatabaseOptions();builder.Configuration.GetSection("Database").Bind(dbOptions);
  • 泛型绑定 GetSection().Get()
// 方式2:泛型绑定(推荐)
var dbOptions = builder.Configuration.GetSection("Database").Get<DatabaseOptions>();
  • 选项模式(依赖注入) 企业级应用
// 方式3:选项模式(依赖注入)
builder.Services.Configure<DatabaseOptions>(builder.Configuration.GetSection("Database"));builder.Services.Configure<ApplicationOptions>(builder.Configuration.GetSection("Application"));

以上的读只是读的一种,这种方式使我们在启动流程中获取相应的配置,然后根据需要初始化服务然后注入到容器中,如:

var builder = WebApplication.CreateBuilder(args);
// 从Configuration中获取值
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
// 注册服务时使用配置
builder.Services.AddDbContext<ApplicationDbContext>(options =>    options.UseSqlServer(connectionString));

还有一种读,就是我们在Controller中获取到IConfiguration对象,然后从中读取到我们需要的配置信息,如:

[ApiController][Route("api/[controller]")]
public class ProductsController : ControllerBase
{    
private readonly IConfiguration _configuration;    
public ProductsController(IConfiguration configuration)    
{        
_configuration = configuration;    
}    
[HttpGet]    
public IActionResult GetProducts()    
{       
 // 直接读取配置(不推荐 - 缺乏类型安全)        
 var pageSize = _configuration.GetValue<int>("Pagination:PageSize", 10);        
 var enableCaching = _configuration.GetValue<bool>("Features:EnableCaching", true);        
 // 使用配置值        
 return Ok(new { PageSize = pageSize, EnableCaching = enableCaching });    
 }
 }

但是这种做法不推荐,一是不简洁,二是缺乏安全类型。POCO,也就是强类型绑定是推荐的做法。这块会在builder.Service.Configure中做介绍。

3. 源码

简单叙述几个重要对象:

  • IConfigurationSource
  • IConfigurationProvider
  • IConfigurationBuilder
  • IConfigurationRoot
  • IConfiguration
    1.IConfigurationSource是个接收器,负责接收外部配置源。需实现其Build方法,该方法把外部配置源传递给自定义实现IConfigurationProvider;- 先接收;
    在这里插入图片描述
    2.IConfigurationProvider就是个读取器,它会加载传入的外部配置源信息;一个接收器对应一个读取器;- 再加载;
    在这里插入图片描述
    3.IConfigurationBuilder是个IConfigurationSource的收集器,通过Add方法把外部配置源放到一个List里,别忘了,builder.Configuration的Configuration继承了IConfigurationBuilder,所以直接Add;- 按先接收再加载的套路重复加入其他配置源;
    在这里插入图片描述
    在这里插入图片描述
    4.IConfigurationRoot又是个provider的收集器,它会把所有的provider收集起来,供通过键查询配置的时候使用;
    在这里插入图片描述
    在这儿收集的;
    在这里插入图片描述
    5.IConfiguration中包含索引器、GetSection、GetChildren等方法,这些方法通过键读取对应的配置,别忘了ConfigurationManager继承自IConfiguration,所以ConfigurationManager拥有以上能力;
    在这里插入图片描述
    ConfigurationManager:
    在这里插入图片描述
    6.所以我们在Program.cs里可以直接通过builder.Configuration.GetSection和builder.Configuration[“key”]获取到配置。闭环。
    在这里插入图片描述
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值