发布于2026-07-23 阅读(0)
扫一扫,手机访问
.NET 中的配置,说穿了就是一堆 key-value 键值对,而且 key 和 value 都是字符串类型。这就像一张巨大的映射表,程序运行时需要从里面查数据。
微软在 .NET 里提供了多种配置提供程序,用来处理不同来源的配置——读、写、重载,一应俱全。我们把 .NET 源码里跟配置相关的类库拿出来看一眼,下面这张图就是所有以 Microsoft.Extensions.Configuration 开头的类库,数量确实不少。

别被数量吓到,咱们拆开来看就简单了。
| 类库名称 | 类库作用 |
|---|---|
| 1、Microsoft.Extensions.Configuration.Abstractions | 定义配置相关的接口,其他所有配置类库都必须引用这个类库 |
| 2、Microsoft.Extensions.Configuration | Microsoft.Extensions.Configuration.Abstractions类库的简单实现 |
| 3、配置提供程序:Microsoft.Extensions.Configuration.CommandLine | 基于命令行的配置提供程序,负责对命令行的配置进行读写、载入、重载等操作。 |
| 4、配置提供程序:Microsoft.Extensions.Configuration.EnvironmentVariables | 基于环境变量的配置提供程序,负责对环境变量的配置进行读写、载入、重载等操作 |
| 5、配置提供程序:Microsoft.Extensions.Configuration.FileExtensions | 基于的文件提供程序的基类库,文件提供程序包括基于Json文件、Ini文件、Xml文件或者自定义文件等。 |
| 6、配置提供程序:Microsoft.Extensions.Configuration.Json | 基于Json文件的配置提供程序程序,负责从Json文本文件中对配置读写、载入、重载等操作。 |
| 7、配置提供程序:Microsoft.Extensions.Configuration.Ini | 基于Ini文件的配置提供程序,负责从Ini文件中对配置进行读写、载入、重载等操作。 |
| 8、配置提供程序:Microsoft.Extensions.Configuration.UserSecrets | 基于UserSecrets的配置提供程序,这个本质上也是一种基于Json文件类型的配置程序。主要用于管理应用机密 |
| 9、Microsoft.Extensions.Configuration.Binder | 负责将key-value键值对的配置列表绑定到指定的C#实体类上,方便程序使用。 |
梳理一下,以上九大件可以分成四组:Abstractions 负责定义接口,Configuration 负责简单实现,第3到第8是具体的配置提供程序,第9个 Binder 呢,就是帮我们把配置绑定到实体类的。
每个配置提供程序都是一个独立的类库,内部结构高度统一:三个文件——配置扩展方法、配置提供程序、配置源。配置源用来生成配置提供程序。另外注意,在第2个类库里,微软已经内置了一个基于内存的配置提供程序,上面表格没单独列出来。
配置源代表一个单独的配置集合:可以是内存里的,也可以是 JSON 文件里的。但它不直接提供读写能力——只有一个 Build 方法,用来返回一个真正的配置提供程序 IConfigurationProvider。后者才是干活的。
public interface IConfigurationSource{ IConfigurationProvider Build(IConfigurationBuilder builder);}
配置提供程序负责真正的操作:设置、读取、重载,最终以键值对的形式暴露配置。
public interface IConfigurationProvider{ bool TryGet(string key, out string? value); void Set(string key, string? value); IChangeToken GetReloadToken(); void Load(); IEnumerable GetChildKeys(IEnumerable earlierKeys, string? parentPath);}
一个程序的配置往往来自多个地方:环境变量、文件、命令行…… 所以就有了 IConfigurationBuilder。它维护着多个配置源,通过 Build 方法生成一个统一的 IConfigurationRoot 来协调全局读写。实际上,IConfigurationRoot 内部遍历所有配置源生成的 IConfigurationProvider,依次尝试获取某个 key 的值。
比如查找 key 为 Name 的配置,就会按顺序在每个 Provider 上调用 TryGet,直到找到为止。
public interface IConfigurationBuilder{ IDictionary Properties { get; } IList Sources { get; } IConfigurationBuilder Add(IConfigurationSource source); IConfigurationRoot Build();}
在 ConfigurationBuilder.Build 方法里,会依次调用每一个配置源的 Build 方法生成 Provider,然后把这些 Provider 塞进 ConfigurationRoot。ConfigurationRoot 通过遍历这些 Provider 来完成实际读写。
public class ConfigurationBuilder : IConfigurationBuilder { private readonly List _sources = new(); public IList Sources => _sources; public IDictionary Properties { get; } = new Dictionary(); public IConfigurationBuilder Add(IConfigurationSource source) { ThrowHelper.ThrowIfNull(source); _sources.Add(source); return this; } public IConfigurationRoot Build() { var providers = new List(); foreach (IConfigurationSource source in _sources) { IConfigurationProvider provider = source.Build(this); providers.Add(provider); } return new ConfigurationRoot(providers); } }
这是最核心的接口,定义了读取、写入、重载配置的方法。它的默认实现就是 ConfigurationRoot,而 ConfigurationRoot 依然是靠各个 Provider 来干活。
public interface IConfiguration{ string? this[string key] { get; set; } IConfigurationSection GetSection(string key); IEnumerable GetChildren(); IChangeToken GetReloadToken();}
IConfigurationRoot 是配置的根接口,它多了一个 Providers 属性,用来保存所有配置提供程序。IConfiguration 的每次访问,本质上都是遍历这个 Providers 列表来完成的。
public interface IConfigurationRoot : IConfiguration{ void Reload(); IEnumerable Providers { get; }}
写一个自定义配置提供程序其实只需要三个类:配置源、配置提供程序、扩展方法(扩展方法不是必须的,但通常都会加)。看看基于命令行的那个类库的文件结构就明白了。

下面演示一个基于数据库的配置提供程序,分别实现配置源 DataBaseConfigurationSource、配置提供程序 DataBaseConfigurationProvider 和扩展方法 DataBaseConfigurationExtensions。这里只是演示骨架,没有真的去读数据库。
public class DataBaseConfigurationSource : IConfigurationSource{ public IConfigurationProvider Build(IConfigurationBuilder builder) { return new DataBaseConfigurationProvider(); }}public class DataBaseConfigurationProvider : ConfigurationProvider{ public override void Load() { base.Load(); // 这里写读取数据库配置的逻辑 }}public static class DataBaseConfigurationExtensions{ public static IConfigurationBuilder AddDb(this IConfigurationBuilder configurationBuilder) { configurationBuilder.Sources.Add(new DataBaseConfigurationSource()); return configurationBuilder; }}
static void Main(string[] args){ var builder = new ConfigurationBuilder() .AddDb() .Build(); var value = builder["key"];}
内存配置就是维护一个 key-value 列表,最简单直接。
static void MemoryConfig(){ List>? initialData = new List>(); initialData.Add(new KeyValuePair("name", "tom")); IConfigurationRoot configuration = new ConfigurationBuilder() .AddInMemoryCollection(initialData) .Build(); Console.WriteLine("name:" + configuration["name"]);}
调用:
static void Main(string[] args){ MemoryConfig();}
这个用得不多,但有时很管用。微软在 Microsoft.Extensions.Configuration 里内置了一个 AddConfiguration 方法,可以把已有的 IConfigurationRoot 包装成一个新的配置提供程序,快速复制出一份一模一样的配置。
static void ChainedConfig(){ List>? initialData = new List>(); initialData.Add(new KeyValuePair("name", "tom")); IConfigurationRoot configuration = new ConfigurationBuilder() .AddInMemoryCollection(initialData) .Build(); IConfigurationRoot newConfiguration = new ConfigurationBuilder() .AddConfiguration(configuration) .Build(); Console.WriteLine("name:" + configuration["name"]);}
命令行配置能自动把传入参数解析成 key-value 对,省去手动分割字符串的麻烦。
static void CommandLineConfig(){ IConfigurationRoot configuration = new ConfigurationBuilder() .AddCommandLine(["name=tom","age=32"]) .Build(); Console.WriteLine("name:" + configuration["name"]);}
.NET 可以读取系统环境变量,还能按前缀过滤。下面例子加载所有以 TEST_ 开头的环境变量。记得添加变量后重启电脑才能生效。
static void EnvironmentConfig(){ IConfigurationRoot configuration = new ConfigurationBuilder() .AddEnvironmentVariables("Test_") .Build(); Console.WriteLine("name:" + configuration["Name"]);}
这是最常用的方式。以下代码从 app.json 加载配置,并开启了文件变更时自动重载。
static void AddJsonFileConfig(){ IConfiguration configuration = new ConfigurationBuilder() .AddJsonFile("app.json", optional: true, reloadOnChange: true) .Build(); Console.WriteLine("name:" + configuration["name"]);}
app.json 内容如下:
{"person":{"name":"caoruipeng","age":12,"school":"北京大学"},"name":"tom11"}
XML 配置同样常见,用法几乎一样。
static void AddXmlFileConfig(){ IConfiguration configuration = new ConfigurationBuilder() .AddXmlFile("app.xml", optional: true, reloadOnChange: true) .Build(); Console.WriteLine("name:" + configuration["name"]);}
app.xml 内容:
tom 21 beijing
Ini 文件现在用得少了,但微软依然支持。
static void AddIniFileConfig(){ IConfiguration configuration = new ConfigurationBuilder() .AddIniFile("app.ini", optional: true, reloadOnChange: true) .Build(); Console.WriteLine("name:" + configuration["person:name"]);}
app.ini 内容:
[person]name=tomage=27
官方提供的提供程序能覆盖绝大多数场景,但如果配置存在注册表或者数据库里,那就得自己动手了。实现起来并不复杂:三个核心类:配置源、配置提供程序、扩展方法。下面是个基于数据库的模拟实现,大家可以把读数据库的代码填进去。
public class DataBaseConfigurationSource : IConfigurationSource{ public IConfigurationProvider Build(IConfigurationBuilder builder) { return new DataBaseConfigurationProvider(); }}public class DataBaseConfigurationProvider : ConfigurationProvider{ public override void Load() { base.Load(); // 读取数据库配置 }}public static class DataBaseConfigurationExtensions{ public static IConfigurationBuilder AddDb(this IConfigurationBuilder configurationBuilder) { configurationBuilder.Sources.Add(new DataBaseConfigurationSource()); return configurationBuilder; }}static void Main(string[] args){ var builder = new ConfigurationBuilder() .AddDb() .Build(); var value = builder["key"];}
以上就是 .NET Core 配置系统的核心脉络,从接口到实现,从内置提供程序到自定义扩展,覆盖了日常开发中最常见的用法。希望对你有帮助。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8