语言运行时标准库JIT编译编译器【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址https://gitcode.com/GitHub_Trending/runtime6/runtime点击查看免费下载导读Microsoft.Extensions.Configuration是 .NET 运行时仓库dotnet/runtime中负责应用配置的核心包它提供了统一的键/值key/value配置抽象让应用可以从内存集合、环境变量、JSON、INI、XML 等多种数据源中以一致的IConfiguration接口读取配置。本文以该包的官方 PACKAGE.md 为主线结合 src/libraries/Microsoft.Extensions.Configuration 与 Microsoft.Extensions.Configuration.Abstractions 两个目录下的真实源码讲透其分层设计、构建流程、链式合并与后者优先的取值规则并给出可直接运行的内存配置示例与自定义 Provider 的落地方法。一、包概览一个核心包 一套抽象 若干数据源 ProviderMicrosoft.Extensions.Configuration包的定位是组合核心配置抽象并围绕它构建不同类型的配置 Provider从而以IConfiguration的形式从各类数据源中检索键/值配置。这句话拆开看包含三个层次抽象层Microsoft.Extensions.Configuration.Abstractions定义IConfiguration、IConfigurationBuilder、IConfigurationProvider、IConfigurationSource、IConfigurationRoot、IConfigurationSection等接口它们构成了整套配置模型的骨架。核心实现层Microsoft.Extensions.Configuration提供ConfigurationBuilder、ConfigurationRoot、ConfigurationSection、ConfigurationManager以及内存、链式两类内置 Provider 与一系列可复用的基类。数据源 Provider 层同一命名空间下的一系列关联包内置了读取环境变量、内存集合、JSON、INI、XML 文件的 Provider 实现除内置实现外社区还发布了大量用于对接各类配置服务和其他数据源的扩展库。本包自身提供的三大关键能力对应 PACKAGE.md 的 Key Features为内存配置 ProviderIn-memory configuration provider直接在代码中以Dictionarystring, string?提供配置链式配置 ProviderChained configuration provider把多个配置 Provider 串联起来实现配置的叠加与合并基类型Base types实现了配置抽象接口的基类供开发者实现自定义 Provider 时继承使用。包内公开的主要类型Main Types为Microsoft.Extensions.Configuration.ConfigurationBuilderMicrosoft.Extensions.Configuration.ConfigurationManagerMicrosoft.Extensions.Configuration.ConfigurationRootMicrosoft.Extensions.Configuration.ConfigurationSection二、核心概念Source、Provider 与 Builder 的三层协作要理解这套体系先厘清三个角色的分工。它们对应 Abstractions 源码目录 中的三个接口文件角色接口职责配置源IConfigurationSourceIConfigurationSource.cs描述数据从哪里来只负责在Build(builder)时产出对应的 Provider配置 ProviderIConfigurationProviderIConfigurationProvider.cs真正加载并持有键/值数据提供Load()、TryGet()、Set()、GetChildKeys()、GetReloadToken()等能力配置构建器IConfigurationBuilderIConfigurationBuilder.cs收集一组 Source调用Build()把它们实例化为 Provider 并组装成最终的IConfigurationRoot从 ConfigurationBuilder.cs 的源码可以看到这套协作的完整闭环public class ConfigurationBuilder : IConfigurationBuilder { private readonly ListIConfigurationSource _sources new(); public IListIConfigurationSource Sources _sources; public IDictionarystring, object Properties { get; } new Dictionarystring, object(); public IConfigurationBuilder Add(IConfigurationSource source) { ArgumentNullException.ThrowIfNull(source); _sources.Add(source); return this; } public IConfigurationRoot Build() { var providers new ListIConfigurationProvider(_sources.Count); foreach (IConfigurationSource source in _sources) { IConfigurationProvider provider source.Build(this); providers.Add(provider); } return new ConfigurationRoot(providers); } }关键点Add()是链式调用的入口。所有形如AddInMemoryCollection()、AddJsonFile()、AddEnvironmentVariables()的扩展方法最终都归结为向_sources列表追加一个IConfigurationSourceBuild()逐个实例化 Provider并保持注册顺序——这个顺序直接决定了后面要讲的后者优先取值规则Properties字典用于在 Builder 与各 Provider 之间共享元数据例如基于文件的 Provider 会借助它传递基路径信息它不属于配置数据本身。最终产物ConfigurationRootBuild()返回的是IConfigurationRoot其默认实现是 ConfigurationRoot.cs。构造函数中ConfigurationRoot会立即对每个 Provider 调用一次p.Load()并为每个 Provider 通过ChangeToken.OnChange(p.GetReloadToken, RaiseChanged)注册重载通知当任意 Provider 触发重载时整个配置根节点会对外广播新的IChangeToken见 ConfigurationRoot.cs 与RaiseChanged方法。ConfigurationRoot还实现了IDisposable释放时会先注销全部变更令牌注册再逐个释放 Provider。三、内存配置 Provider 实战最小可运行示例内存配置 Provider 是最简单、也最适合理解整套模型约定的入口。PACKAGE.md 给出了完整示例下面结合源码逐行解读using Microsoft.Extensions.Configuration; var configurationBuilder new ConfigurationBuilder(); configurationBuilder.AddInMemoryCollection( new Dictionarystring, string? { [Setting1] value, [MyOptions:Enabled] bool.TrueString, }); configurationBuilder.AddInMemoryCollection( new Dictionarystring, string? { [Setting2] value2, [MyOptions:Enabled] bool.FalseString, }); var config configurationBuilder.Build(); // note case-insensitive Console.WriteLine(config[setting1]); Console.WriteLine(config[setting2]); // note last in wins Console.WriteLine(config[MyOptions:Enabled]);这段代码演示了三个必须掌握的语义大小写不敏感config[setting1]能命中Setting1。原因在 ConfigurationProvider.cs所有 Provider 基类的内部字典都使用StringComparer.OrdinalIgnoreCase构造键的比较与查找天然忽略大小写。后者优先last in winsMyOptions:Enabled被两个 Provider 先后赋值TrueString与FalseString最终读取到的是后注册 Provider 的FalseString。原因在 ConfigurationRoot.cs 的GetConfiguration读取时从 Provider 列表的末尾向前遍历返回第一个命中键的 Provider 的值而Build()中 Provider 的排列顺序与Add注册顺序一致因此后注册的覆盖先注册的。这恰好对应示例注释note last in wins。键路径section pathMyOptions:Enabled中的冒号:是键的分层分隔符见 ConfigurationPath.cs 中KeyDelimiter的约定它把扁平化的键组织成树状的 Section 结构。扩展方法背后的源码链路AddInMemoryCollection定义在 MemoryConfigurationBuilderExtensions.cs有两个重载无参版本Add(new MemoryConfigurationSource())初始数据为空之后可通过 Provider 实例动态Add键值带initialData版本Add(new MemoryConfigurationSource { InitialData initialData })。MemoryConfigurationSourceMemoryConfigurationSource.cs是一个极简的IConfigurationSource只暴露InitialData属性Build()返回new MemoryConfigurationProvider(this)。而MemoryConfigurationProviderMemoryConfigurationProvider.cs在构造时把InitialData逐条拷贝进基类的Data字典并额外实现了IEnumerableKeyValuePairstring, string?方便直接枚举。四、可复用的基类实现自定义 Provider 的脚手架PACKAGE.md 强调本包提供实现配置抽象接口的基类型可用于实现其他配置 Provider。这正是ConfigurationProvider抽象基类ConfigurationProvider.cs的职责它已为你实现绝大部分样板逻辑数据存储protected IDictionarystring, string? Data构造时使用大小写不敏感的比较器查找与写入TryGet()/Set()直接操作Data字典加载钩子public virtual void Load() { }默认空实现派生类只需覆写此方法从自己的数据源填充Data子键枚举GetChildKeys(earlierKeys, parentPath)默认实现会解析冒号路径把A:B:C之类键的第一段作为直接子节返回并合并前面 Provider 的键后按ConfigurationKeyComparer排序变更通知GetReloadToken()返回内部ConfigurationReloadToken覆写Load()的派生类在重新加载数据后调用受保护的OnReload()即可广播配置已刷新。因此编写一个新 Provider 的最小形态是继承ConfigurationProvider实现Load()填充Data再写一个对应的IConfigurationSource子类负责在Build()中实例化它。仓库里基于文件的StreamConfigurationProvider/StreamConfigurationSourceStreamConfigurationProvider.cs就是这种模式的示范——JSON、INI、XML Provider 全部派生自这一对基类只需各自实现流解析逻辑。五、链式配置 Provider把多个配置合并成一个配置链式配置 ProviderChained configuration provider用于把多个配置 Provider 串联在一起其价值在于你可以先构造一个独立的IConfiguration例如加载默认值的内存配置再通过AddConfiguration()把它作为一层 Source 接入新的 Builder从而在保留分层覆盖语义的同时复用已有配置对象。其源码实现由三部分组成ChainedConfigurationSourceChainedConfigurationSource.cs属性Configuration指向要接入的现有IConfigurationShouldDisposeConfiguration控制当 Provider 被释放时是否连带释放该配置对象ChainedBuilderExtensions.AddConfiguration()ChainedBuilderExtensions.cs提供AddConfiguration(config)与AddConfiguration(config, shouldDisposeConfiguration)两个重载默认shouldDisposeConfiguration: falseChainedConfigurationProviderChainedConfigurationProvider.cs把对自身键的TryGet/Set请求转发给被链入的_configGetReloadToken()也直接透传其重载令牌Load()的首次调用是无操作被链入的配置在接入前已加载完成避免多余的通知后续调用则转发给内部ConfigurationRoot的全部 Provider。using Microsoft.Extensions.Configuration; var baseConfig new ConfigurationBuilder() .AddInMemoryCollection(new Dictionarystring, string? { [Logging:Level] Information, [ConnectionStrings:Default] Serverbase;, }) .Build(); var finalConfig new ConfigurationBuilder() .AddConfiguration(baseConfig) // 默认不接管其生命周期 .AddInMemoryCollection(new Dictionarystring, string? { [Logging:Level] Debug, // 覆盖上层值 }) .Build(); Console.WriteLine(finalConfig[Logging:Level]); // Debug后者优先 Console.WriteLine(finalConfig[ConnectionStrings:Default]); // Serverbase;这里可以看到链式与内存两种 Provider 在同一 Builder 中协同最终读取Logging:Level时后注册的内存 Provider 胜出读取ConnectionStrings:Default时链式 Provider 从baseConfig中取到值。Hosting模型WebApplicationBuilder/HostApplicationBuilder正是通过类似机制把appsettings.json、appsettings.{Environment}.json、用户机密、环境变量、命令行参数等按固定顺序叠加成最终的IConfiguration。六、分层读取ConfigurationSection 与配置树IConfiguration接口IConfiguration.cs只承诺四个成员索引器this[string key]、GetSection(key)、GetChildren()与GetReloadToken()。基于冒号路径扁平键集合被组织成树形结构树上的每个节点就是一个IConfigurationSection。ConfigurationSectionConfigurationSection.cs是默认实现几个值得注意的实现细节永不返回 nullGetSection()找不到对应节点时返回一个空的 SectionValue为 null这让代码可以安全地链式调用而不必判空Path 与 Key 分离Path是节从根到自身的完整路径如MyOptionsKey是路径最后一段通过ConfigurationPath.GetSectionKey惰性计算透传读写Section 的Value、索引器、GetSection()、GetChildren()、GetReloadToken()全部委托给持有的_root因此任意层级的 Section 都能访问整棵配置树也都能感知根节点的重载事件。配合 ConfigurationRootExtensions.cs 中的GetConnectionString(key)、GetSection(key)等扩展以及Microsoft.Extensions.Configuration.Binder包的GetT()/Bind()方法扁平键可以直接绑定到强类型选项对象——这正是 ASP.NET Core 中IOptionsT体系的底层数据来源。七、ConfigurationManager可热更新的动态配置入口除ConfigurationBuilder外本包还提供ConfigurationManagerConfigurationManager.cs它是IConfigurationBuilder与IConfigurationRoot的双重实现也实现了IDisposable。与先建后取的 Builder 不同ConfigurationManager允许在构建完成、应用运行期间继续Add新的配置源并借助内部的ReferenceCountedProviders/ReferenceCountedProvidersManagerReferenceCountedProvidersManager.cs管理 Provider 集合的引用计数与重建从而支持配置源的热追加。从仓库 ConfigurationManagerTest.cs 的测试覆盖可以看到它重点验证了追加源后的重载通知、值覆盖顺序以及与 Builder 行为的等价性。Host框架与WebApplicationBuilder在解析appsettings.json等文件时即使用ConfigurationManager这也是reloadOnChange: true的配置文件能在运行时被感知的机制基础。八、内置数据源家族与关联包导览PACKAGE.md 的 Related Packages 罗列了围绕本包生态的关联包它们都以本包的核心抽象为地基各自提供一个或多个数据源 Provider关联包提供的数据源Microsoft.Extensions.Configuration.JsonJSON 文件AddJsonFileMicrosoft.Extensions.Configuration.IniINI 文件AddIniFileMicrosoft.Extensions.Configuration.XmlXML 文件AddXmlFileMicrosoft.Extensions.Configuration.EnvironmentVariables环境变量AddEnvironmentVariablesMicrosoft.Extensions.Configuration.CommandLine命令行参数AddCommandLineMicrosoft.Extensions.Configuration.UserSecrets开发期用户机密AddUserSecretsMicrosoft.Extensions.Configuration.FileExtensions文件型 Provider 的公共基类能力路径解析、文件监控与reloadOnChange支持Microsoft.Extensions.Configuration.Binder配置到强类型对象的绑定GetT/Bind这些 Provider 全部遵循本包的三层模型扩展方法创建 Source → Source 的Build()产出 Provider → Provider 的Load()填充大小写不敏感的Data字典。因此无论配置来自文件还是环境变量应用层面对外的读取接口始终是同一个IConfiguration。九、深入验证从测试代码看契约行为仓库自带的测试是理解契约的最佳佐证与本文核心语义直接相关的测试包括ConfigurationTest.cs 与 ConfigurationProviderTestBase.cs系统性地覆盖键查找的大小写不敏感性、多个 Provider 间的覆盖顺序、Section 枚举、值设置与重载等行为ChainedConfigurationProviderTests.cs验证链式 Provider 的取值透传、子键合并与排序ConfigurationManagerTest.cs验证运行期追加配置源的行为FunctionalTests/ConfigurationTests.cs以端到端方式把内存、环境变量等多种 Provider 组合起来验证后者优先与键路径解析在真实组合场景下的表现。阅读这些测试可以快速确认某个语义到底是文档说法还是真实行为——例如在 ConfigurationRoot.cs 中GetConfiguration从后向前遍历 Provider 的实现与测试中last provider wins的断言完全一致。十、小结与推荐路径Microsoft.Extensions.Configuration用一套极简接口IConfiguration只有四个成员统一了 .NET 生态中几乎所有配置来源的访问方式用 Builder 收集 Source用 Provider 加载数据用后注册覆盖先注册的规则合并取值用冒号路径组织树形 Section用 ChangeToken 感知重载。理解这五条契约就掌握了 .NET 配置体系的全貌也具备了阅读任何第三方配置 Provider 源码的能力。建议继续深入阅读的仓库路径核心实现src/libraries/Microsoft.Extensions.Configuration/srcConfigurationBuilder、ConfigurationRoot、ConfigurationSection、ConfigurationProvider、ChainedConfigurationProvider抽象接口src/libraries/Microsoft.Extensions.Configuration.Abstractions/srcIConfiguration、IConfigurationBuilder、IConfigurationProvider、IConfigurationSource行为验证src/libraries/Microsoft.Extensions.Configuration/tests单元测试与功能测试官方文档Configuration in .NET 与 Microsoft.Extensions.Configuration 命名空间 相关章节如果需要代码级参考可直接查看本仓库的 Abstractions 包 README 与 Configuration 包 README 了解构建与使用约定。最后提示Microsoft.Extensions.Configuration以 MIT 协议开源反馈与贡献请通过仓库的 Issues 与 PR 流程进行。赞分享语言运行时标准库JIT编译编译器【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址https://gitcode.com/GitHub_Trending/runtime6/runtime点击查看免费下载相关推荐Kedro 配置加载体系的抽象基类AbstractConfigLoader 深度解析Kedro 配置加载体系的抽象基类AbstractConfigLoader 深度解析 kedro.config.AbstractConfigLoader 是数据工程工作流自动化three.js Light 光照抽象基类解析继承体系、核心属性与资源释放机制three.js Light 光照抽象基类解析继承体系、核心属性与资源释放机制 Light 是 three.js 中所有光源的抽象基类 AmbientLig前端3D渲染图形学AI SDK Provider 抽象架构深度解析AI Functions、V4 模型规范与 Provider 实现AI SDK Provider 抽象架构深度解析AI Functions、V4 模型规范与 Provider 实现 导读 本文基于 AI SDK 仓库中的架构人工智能AI 应用AI Agent工具调用MCP Clients创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
