.NET应用如何加载多个 appsettings.json 文件
在 .NET 应用中,通常使用 appsettings.json
文件存储应用的配置信息。对于有多个环境的项目,通常还会针对每个环境,再创建一个 appsettings.{Environment}.json
用于存储特定于每个环境的配置,比如 appsettings.Development.json
、appsettings.Production.json
等。然后,可以在代码中,加载并合并 appsettings.json
和 appsettings.{Environment}.json
。对于简单的值为字符串类型的配置,合并规则简单明了:直接覆盖即可。但是,如果配置项是复杂结构,比如嵌套的字典和数组,那么合并多个配置文件时,是什么规则呢?
简单地说:对于嵌套的字典,那么根据字典的键逐层进行覆盖或者增加;而数组其实是被当作字典对待的,数组的索引是键的一部分,然后按照字典的规则进行合并。
下面通过简单的代码进行演示。
代码示例 🔗
首先创建一个C#的 .NET 控制台程序,并且安装处理配置的包 Microsoft.Extensions.Configuration.Json
。同时将 appsettings.json
和 appsettings.Development.json
文件添加到项目文件清单中。最终,csproj 文件的内容为:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
<Content Include="appsettings.json;appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
程序代码文件 Program.cs
的内容为:
using Microsoft.Extensions.Configuration;
class Program
{
static void Main()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.Development.json", optional: false, reloadOnChange: true)
.Build();
foreach (var item in configuration.AsEnumerable())
{
Console.WriteLine($"{item.Key} -> {item.Value}");
}
}
}
从代码中可以看出,其实每个配置项(即 item
)都是键值对,其类型为 KeyValuePair<string, string?>
。
appsettings.json
内容如下:
{
"Transforms": [
{ "RequestHeaderOriginHost": "true" }
]
}
appsettings.Development.json
的内容如下:
{
"Transforms": [
{ "PathRemovePrefix": "/prefix" },
{ "RequestHeaderOriginHost": "false" }
]
}
运行结果 🔗
构建和运行应用,控制台输出为:
Transforms ->
Transforms:1 ->
Transforms:1:RequestHeaderOriginHost -> false
Transforms:0 ->
Transforms:0:RequestHeaderOriginHost -> true
Transforms:0:PathRemovePrefix -> /prefix
如果将其还原成 JSON 格式,那么就得到合并后的 JSON,其实为:
{
"Transforms": [
{"RequestHeaderOriginHost": "true", "PathRemovePrefix": "/prefix"},
{"RequestHeaderOriginHost": "false"}
]
}
这可能并不是期望的结果。
从控制台的输出,还可以看到:在迭代每个配置项时,对于值为数组的元素,并没有按照数组下标遍历。而是先输出第二个元素(即 Transforms:1
),再输出第一个元素(即 Transforms:0
)。