02020304 .NET Core核心基础组件04-配置系统、Json文件配置、选项方式读取、扁平化&环境变量&其它配置源
02020304 .NET Core核心基础组件04-配置系统、Json文件配置、选项方式读取、扁平化&环境变量&其它配置源
1. 配置系统入门(视频2-32)
- 传统Web.config配置的缺点,之前DI讲过。
- 为了兼容,仍然可以使用web.config和ConfigurationManage类,但不推荐。
- .NET中的配置系统支持丰富的配置源,包括文件(json、xml、ini等)、注册表、环境变量、命令行、Azure key value等,此外还可以配置自定义配置源。
- 可以跟踪配置的改变,可以按照优先级覆盖。
2. Json文件配置
2.1 Json文件配置步骤
- step1 → 创建Json文件,文件名随意。比如config.json,设置如果教新则复制。参考备注。
- 注意要将Json文件的属性设定为较新则复制,这样文件才会拷贝到和.exe文件同级的目录底下。这样程序运行的时候,是读取的的与.exe文件同级的Json文件,不再加载源代码里面的Json文件。
- step2 → NuGet安装两个包
- Microsoft.Extensions.Configuration → 配置框架的包。配置框架可以读Json文件、xml文件、ini文件、数据库、环境变量来读。
- Microsoft.Extensions.Configuration.Json → 读Json文件的包
- step3 → 编写代码,先用简单的方式读取配置。
- 拓展知识
- 15-20年前,用xml配置。一层套一层,贼恶心
- 现在流行Json格式来做配置。
- 自行网上查阅Json格式的资料。
2.2 Json格式
{"a":"3","b":"5",c:{"d":"7","ids":[3,5]},} // 可以多级嵌套
2.3 新建Json文件
- 项目名称 → 右键 → 添加 → 新建项 → 文本文件 → 名称 → config.json
// 新建:config.json
{
"name": "yzk",
"age": "18",
"qinway": {"address":"wuxi","port":"80"}
}
说明:需要把config.json文件的属性修改为如果较新则复制。
2.4 引入两个包
install-package Microsoft.Extensions.Configuration // 老师演示包的版本:5.0.0。截止2025.09.10,该包的版本为:9.0.9
install-package Microsoft.Extensions.Configuration.Json // 老师演示包的版本:5.0.0。截止2025.09.10,该包的版本为:9.0.9
2.5 读取配置原始方法

- ConfigurationBuilder类 → 用来对Configuration进行配置的构建器。
- AddJsonFile方法 → 加载配置文件
- config.json → 文件名
- optional:false → optional是可选参数。
- false表示文件不存在就不报错。文件存在我就读,文件不存在不报错也不读。
- 对于初学者建议设定为true,避免因为Json文件名、代码写的有问题导致写错了发现不了。
- reloadOnChange → 文件修改之后是否立即加载新的配置。
- true表示不需要程序重启,配置文件修改之后,立即读到新的配置文件。建议为true。
- false表示如果配置文件更改了,需要重启程序才能加载新的配置。
- config对象 → 通过该对象读取配置。IConfigurationRoot是配置项读取器。
- Json里面所有值默认为字符串类型。
- config.GetSection("proxy:address").Value → 用于读取多级结构。
2.6 读取Json文件示例
using Microsoft.Extensions.Configuration;
using System;
namespace JsonConfig
{
class Program
{
static void Main(string[] args)
{
ConfigurationBuilder configBuider = new ConfigurationBuilder();
configBuider.AddJsonFile("config.json", optional : true, reloadOnChange : true);
IConfigurationRoot configRoot = configBuider.Build();
string name = configRoot["name"];
Console.WriteLine($"name = {name}");
string addr = configRoot.GetSection("qinway:address").Value;
Console.WriteLine($"addr = {addr}");
Console.ReadLine();
}
}
}
控制台输出:
name = yzk
addr = wuxi
2.7 关于config.json文件说明

- 此时如果我们手动的修改拷贝到.exe目录下的config.json文件,然后直接双击.exe文件,程序输出的是修改后的内容。
2.8 绑定读取配置

install-package Microsoft.Extensions.Configuration.Binder // 老师演示包的版本:5.0.0。截止2025.09.10,该包的版本为:9.0.9
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using Microsoft.Extensions.Configuration;
using System;
namespace JsonConfig
{
class Program
{
static void Main(string[] args)
{
ConfigurationBuilder configBuider = new ConfigurationBuilder();
configBuider.AddJsonFile("config.json", optional : true, reloadOnChange : true);
IConfigurationRoot configRoot = configBuider.Build();
Qinway qinway = configRoot.GetSection("Qinway").Get<Qinway>(); // @1
Console.WriteLine($"{qinway.Address}, {qinway.Port}");
Console.ReadLine();
}
}
class Qinway // 类名要和配置名一致,貌似不区分大小写规范。
{
public string Address { get; set; }
public int Port { get; set; }
}
}
控制台输出
wuxi, 80
说明:
1. 在@1处GetSection("Qinway"),这里的Qinway和config.json里面的qinway对应,不区分大小写。
2. 在@1处Get<Qinway>()是个泛型方法,Qinway是类名。
2.8 将Json文件根节点读出来
using Microsoft.Extensions.Configuration;
using System;
namespace JsonConfig
{
class Program
{
static void Main(string[] args)
{
ConfigurationBuilder configBuider = new ConfigurationBuilder();
configBuider.AddJsonFile("config.json", optional : true, reloadOnChange : true);
IConfigurationRoot configRoot = configBuider.Build();
Config cg = configRoot.Get<Config>();
Console.WriteLine($"{cg.Name}, {cg.Qinway.Port}");
Console.ReadLine();
}
}
class Qinway
{
public string Address { get; set; }
public int Port { get; set; }
}
class Config // 根节点类
{
public string Name { get; set; }
public int Age { get; set; }
public Qinway Qinway { get; set; }
}
}
控制台输出:
yzk, 80
3. 选项方式读取(视频2-33)
3.1 选项方式读取用法

- IOptions
→ 读取配置,不会读到新的值。即使配置文件改了,通过这种方式读的仍然是旧的值。 - 只有在程序重启之后,读的才是新的值。
- IOptionsMonitor
→ 读取配置,会读到新的值。 - IOptionsSnapshot
→ 读取配置,会读到新的值。截图有错误,更正为IOptionsSnapshot 会在同一个范围之内。
3.2 演示代码

3.3 项目目录
JsonConfig → 解决方案名称
├── JsonConfig → .NET Core 5.0控制台项目。
| ├── config.json → Json文件
| ├── TestController.cs → DI注入用的类,用来读取整个Json文件
| ├── TestPart.cs → DI注入用的类,用来读取Json文件某个节点
└── └──Program.cs → 包含Main方法,程序的入口。
需要安装如下5个包:
microsoft.extensions.configuration
microsoft.extensions.configuration.binder
microsoft.extensions.configuration.json
microsoft.extensions.options
microsoft.extensions.dependencyinjection
3.4 源码
// config.json
{
"name": "yzk",
"age": "18",
"qinway": {"address":"wuxi","port":"80"}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// TestController.cs
using Microsoft.Extensions.Options;
using System;
namespace JsonConfig
{
class TestController
{
public readonly IOptionsSnapshot<Config> optConfig;
public TestController(IOptionsSnapshot<Config> optConfig)
{
this.optConfig = optConfig;
}
public void Test() // 测试读取
{
Config config = optConfig.Value;
Console.WriteLine(config.Age);
Console.WriteLine("**********************************");
Console.WriteLine(config.Age);
}
}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// TestPart.cs
using Microsoft.Extensions.Options;
using System;
namespace JsonConfig
{
class TestPart
{
public readonly IOptionsSnapshot<Qinway> optQinway;
public TestPart(IOptionsSnapshot<Qinway> optQinway)
{
this.optQinway = optQinway;
}
public void TestRead() // 测试读取
{
Console.WriteLine(optQinway.Value.Address);
Console.WriteLine(optQinway.Value.Port);
}
}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Program.cs
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace JsonConfig
{
class Program
{
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<TestController>(); // 往DI容器注册
services.AddScoped<TestPart>(); // 往DI容器注册
ConfigurationBuilder configBuider = new ConfigurationBuilder();
configBuider.AddJsonFile("config.json", optional : true, reloadOnChange : true);
IConfigurationRoot configRoot = configBuider.Build();
// @1 把Config对象绑定到根节点
services.AddOptions().Configure<Config>(e => configRoot.Bind(e));
// @2 把Qinway对象绑定到qinway节点
services.AddOptions().Configure<Qinway>(e => configRoot.GetSection("qinway").Bind(e));
/*
* 在@1处和@2处的代码可以写成如下形式
* services.AddOptions()
* .Configure<Config>(e => configRoot.Bind(e));
* .Configure<Qinway>(e => configRoot.GetSection("qinway").Bind(e));
* 即:可以连续点来绑定节点。
*/
using (var sp = services.BuildServiceProvider())
{
var c1 = sp.GetRequiredService<TestController>();
c1.Test();
var c2 = sp.GetRequiredService<TestPart>();
c2.TestRead();
}
Console.ReadLine();
}
}
class Qinway // 单个节点类
{
public string Address { get; set; }
public int Port { get; set; }
}
class Config // 根节点类
{
public string Name { get; set; }
public int Age { get; set; }
public Qinway Qinway { get; set; }
}
}
控制台输出:
18
**********************************
18
wuxi
80
3.5 演示修改本地配置文件后输出结果
// 修改Program.cs文件
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace JsonConfig
{
class Program
{
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<TestController>(); // 往DI容器注册
services.AddScoped<TestPart>(); // 往DI容器注册
ConfigurationBuilder configBuider = new ConfigurationBuilder();
configBuider.AddJsonFile("config.json", optional : true, reloadOnChange : true);
IConfigurationRoot configRoot = configBuider.Build();
// @1 把Config对象绑定到根节点
services.AddOptions().Configure<Config>(e => configRoot.Bind(e));
// @2 把Qinway对象绑定到qinway节点
services.AddOptions().Configure<Qinway>(e => configRoot.GetSection("qinway").Bind(e));
/*
* 在@1处和@2处的代码可以写成如下形式
* services.AddOptions()
* .Configure<Config>(e => configRoot.Bind(e));
* .Configure<Qinway>(e => configRoot.GetSection("qinway").Bind(e));
* 即:可以连续点来绑定节点。
*/
using (var sp = services.BuildServiceProvider())
{
while(true)
{
using (var scope = sp.CreateScope()) // 使用IOptionsSnapshot配置时,在下一个Scope生效。
{
var c1 = scope.ServiceProvider.GetRequiredService<TestController>();
c1.Test();
var c2 = scope.ServiceProvider.GetRequiredService<TestPart>();
c2.TestRead();
}
Console.WriteLine("点击任意键继续");
Console.ReadLine();
}
}
}
}
class Qinway // 单个节点类
{
public string Address { get; set; }
public int Port { get; set; }
}
class Config // 根节点类
{
public string Name { get; set; }
public int Age { get; set; }
public Qinway Qinway { get; set; }
}
}
step1 → 控制台输出:
18
**********************************
18
wuxi
80
点击任意键继续
step2 → 修改本地配置文件为
{
"name": "yzk",
"age": "88",
"qinway": {"address":"wuhan","port":"60"}
}
step3 → 控制台输出:
18
**********************************
18
wuxi
80
点击任意键继续
注意:这里示例失败了,不纠结,继续推进课程。
4. 其它配置提供者(视频2-34)
4.1 命令行方式配置

4.2 项目目录
JsonConfig → 解决方案名称
├── JsonConfig → .NET Core 5.0控制台项目。
| ├── config.json → Json文件
| ├── TestController.cs → DI注入用的类,用来读取整个Json文件
| ├── TestPart.cs → DI注入用的类,用来读取Json文件某个节点
└── └──Program.cs → 包含Main方法,程序的入口。
需要安装如下6个包:
microsoft.extensions.configuration
microsoft.extensions.configuration.binder
microsoft.extensions.configuration.json
microsoft.extensions.options
microsoft.extensions.dependencyinjection
microsoft.extensions.configuration.commandline
4.3 启动命令行位置

4.4 源代码
- 在3.4基础上修改Program.cs文件
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace JsonConfig
{
class Program
{
static void Main(string[] args) // 这里args是命令行参数,不懂。
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<TestController>();
services.AddScoped<TestPart>();
ConfigurationBuilder configBuider = new ConfigurationBuilder();
// configBuider.AddJsonFile("config.json", optional : true, reloadOnChange : true);
configBuider.AddCommandLine(args); // 将args传入。
IConfigurationRoot configRoot = configBuider.Build();
services.AddOptions()
.Configure<Config>(e => configRoot.Bind(e))
.Configure<Qinway>(e => configRoot.GetSection("qinway").Bind(e));
using (var sp = services.BuildServiceProvider())
{
while(true)
{
using (var scope = sp.CreateScope())
{
var c1 = scope.ServiceProvider.GetRequiredService<TestController>();
c1.Test();
Console.WriteLine("改一下age");
Console.ReadKey();
c1.Test();
var c2 = scope.ServiceProvider.GetRequiredService<TestPart>();
c2.TestRead();
}
Console.WriteLine("点击任意键继续");
Console.ReadLine();
}
}
}
}
class Qinway
{
public string Address { get; set; }
public int Port { get; set; }
}
class Config
{
public string Name { get; set; }
public int Age { get; set; }
public Qinway Qinway { get; set; }
}
}
控制台输出:
0
**********************************
0
改一下age
4.5 命令行启动程序并且输入配置

- 说明:命令行只有在程序运行时才能配置,不存在改配置的问题,这样调试比较麻烦。
4.6 通过VS进行配置
- 项目名称 → 属性 → 调试 → 应用程序参数。

- 输出结果对比
4.4中控制台输出:
0
**********************************
0
改一下age
在VS 2019中配置了应用程序参数之后,控制台输出:
18
**********************************
18
改一下age
5. 扁平化配置

- 对于命令行来讲,都是名称=值这样的形式,无法嵌套结构。此时通过扁平化来配置。
6. 环境变量配置

7. 其它配置源

结尾
书籍:ASP.NET Core技术内幕与项目实战
视频:https://www.bilibili.com/video/BV1pK41137He
著:杨中科
ISBN:978-7-115-58657-5
版次:第1版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※