.NET 中的配置
.NET 中的配置是使用一个或多个配置提供程序执行的。 配置提供程序使用各种配置源从键值对读取配置数据:
- 设置文件,例如 appsettings.json
- 环境变量
- Azure Key Vault
- Azure 应用配置
- 命令行参数
- 已安装或已创建的自定义提供程序
- 目录文件
- 内存中的 .NET 对象
- 第三方提供程序
备注
有关配置 .NET 运行时本身的信息,请参阅 .Net 运行时配置设置。
概念和抽象
给定一个或多个配置源,IConfiguration 类型提供配置数据的统一视图。 配置是只读的,配置模式并未设计为可以编程方式写入。 IConfiguration
接口是所有配置源的单个表示形式,如下图所示:
配置控制台应用
在默认情况下,使用 dotnet new 命令模板或 Visual Studio 创建的 .NET 控制台应用程序不会公开配置功能。 若要在新的 .NET 控制台应用程序中添加配置,请添加对 Microsoft.Extensions.Configuration 的包引用。 此包是 .NET 应用中配置的基础。 它提供 ConfigurationBuilder 和相关类型。
using Microsoft.Extensions.Configuration;
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>()
{
["SomeKey"] = "SomeValue"
})
.Build();
Console.WriteLine(configuration["SomeKey"]);
// Outputs:
// SomeValue
前面的代码:
- 创建新的 ConfigurationBuilder 实例。
- 将键值对的内存中集合添加到配置生成器。
- 调用 Build() 方法创建 IConfiguration 实例。
- 将
SomeKey
键的值写入控制台。
虽然此示例使用内存中配置,但有许多配置提供程序可用,为基于文件的、环境变量、命令行参数和其他配置源公开功能。 有关详细信息,请参阅 .NET 中的配置提供程序。
替代托管方法
通常,应用不仅会读取配置。 它们可能会使用依赖项注入、记录和其他服务。 对于使用这些服务的应用,建议使用 .NET 通用主机方法。 相反,请考虑添加包引用到 Microsoft.Extensions.Hosting。 修改 Program.cs 文件,使其与以下代码相匹配:
using Microsoft.Extensions.Hosting;
using IHost host = Host.CreateApplicationBuilder(args).Build();
// Application code should start here.
await host.RunAsync();
Host.CreateApplicationBuilder(String[]) 方法按照以下顺序为应用提供默认配置(从最高优先级到最低优先级):
- 使用命令行配置提供程序通过命令行参数提供。
- 使用环境变量配置提供程序通过环境变量提供。
- 应用在
Development
环境中运行时的应用机密。 - 使用 JSON 配置提供程序通过 appsettings.json 提供。
- 使用 JSON 配置提供程序通过 appsettings.
Environment
.json 提供 。 例如,appsettings.Production.json 和 appsettings.Development.json。 - ChainedConfigurationProvider:添加现有的
IConfiguration
作为源。
添加配置提供程序会替代以前的配置值。 例如,命令行配置提供程序会替代来自其他提供程序的所有值,因为它最后添加。 如果在 appsettings.json 和环境中都设置了 SomeKey
,则使用环境值,因为它是在 appsettings.json 之后添加的。
绑定
使用 .NET 配置抽象的其中一个关键优点是,可将配置值绑定到 .NET 对象的实例。 例如,JSON 配置提供程序可用于将 appsettings.json 文件映射到 .NET 对象,并用于依赖关系注入。 这可以实现选项模式,它使用类来提供对相关设置组的强类型访问。 .NET 配置提供各种抽象。 请考虑以下接口:
- IConfiguration:表示一组键/值应用程序配置属性。
- IConfigurationRoot 表示
IConfiguration
层次结构的根。 - IConfigurationSection:表示应用程序配置值的一个部分。
这些抽象与它们的底层配置提供程序 (IConfigurationProvider) 无关。 换句话说,你可以使用 IConfiguration
实例来访问多个提供程序的任何配置值。
绑定器可以使用不同的方法来处理配置值:
- 对于基元类型,采用直接反序列化(使用内置转换器)。
- 当类型有一个复杂类型时,使用 TypeConverter。
- 对于具有属性的复杂类型,使用反射。
注意
绑定器有一些限制:
- 如果属性具有专用资源库或无法转换其类型,则将被忽略。
- 将忽略没有相应配置键的属性。
绑定层次结构
配置值可以包含分层数据。 分层对象使用配置键中的 :
分隔符表示。 若要访问配置值,请使用 :
字符分隔层次结构。 例如,请考虑以下配置值:
{
"Parent": {
"FavoriteNumber": 7,
"Child": {
"Name": "Example",
"GrandChild": {
"Age": 3
}
}
}
}
下表表示前面的示例 JSON 的示例键及其相应值:
密钥 | 值 |
---|---|
"Parent:FavoriteNumber" |
7 |
"Parent:Child:Name" |
"Example" |
"Parent:Child:GrandChild:Age" |
3 |
基本示例
若要访问基本格式的配置值,无需通用主机方法的帮助,可以直接使用 ConfigurationBuilder 类型。
提示
System.Configuration.ConfigurationBuilder 类型不同于 Microsoft.Extensions.Configuration.ConfigurationBuilder 类型。 所有这些内容都特定于 Microsoft.Extensions.*
NuGet 包和命名空间。
来看看以下 C# 项目:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
</ItemGroup>
</Project>
前面的项目文件引用了几个配置 NuGet 包:
- Microsoft.Extensions.Configuration.Binder:将对象与
Microsoft.Extensions.Configuration
的配置提供程序中的数据绑定的功能。 - Microsoft.Extensions.Configuration.Json:
Microsoft.Extensions.Configuration
的 JSON 配置提供程序实现。 - Microsoft.Extensions.Configuration.EnvironmentVariables:
Microsoft.Extensions.Configuration
的环境变量配置提供程序实现。
来看一个示例 appsettings.json 文件:
{
"Settings": {
"KeyOne": 1,
"KeyTwo": true,
"KeyThree": {
"Message": "Oh, that's nice...",
"SupportedVersions": {
"v1": "1.0.0",
"v3": "3.0.7"
}
},
"IPAddressRange": [
"46.36.198.121",
"46.36.198.122",
"46.36.198.123",
"46.36.198.124",
"46.36.198.125"
]
}
}
现在,给定此 JSON 文件,下面是一个直接使用配置生成器的示例消耗模式:
using Microsoft.Extensions.Configuration;
// Build a config object, using env vars and JSON providers.
IConfigurationRoot config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build();
// Get values from the config given their key and their target type.
Settings? settings = config.GetRequiredSection("Settings").Get<Settings>();
// Write the values to the console.
Console.WriteLine($"KeyOne = {settings?.KeyOne}");
Console.WriteLine($"KeyTwo = {settings?.KeyTwo}");
Console.WriteLine($"KeyThree:Message = {settings?.KeyThree?.Message}");
// Application code which might rely on the config could start here.
// This will output the following:
// KeyOne = 1
// KeyTwo = True
// KeyThree:Message = Oh, that's nice...
上述 C# 代码:
- 将 ConfigurationBuilder 实例化。
- 添加
"appsettings.json"
文件,以便由 JSON 配置提供程序识别。 - 添加环境变量,以便由环境变量配置提供程序识别。
- 使用
config
实例获取所需的"Settings"
部分和相应的Settings
实例。
Settings
对象的结构如下所示:
public sealed class Settings
{
public required int KeyOne { get; set; }
public required bool KeyTwo { get; set; }
public required NestedSettings KeyThree { get; set; } = null!;
}
public sealed class NestedSettings
{
public required string Message { get; set; } = null!;
}
使用托管的基本示例
若要访问 IConfiguration
值,你可以再次依靠 Microsoft.Extensions.Hosting
NuGet 包。 创建一个新的控制台应用程序,并将以下项目文件内容粘贴到其中:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
</Project>
前面的项目文件定义了:
- 该应用程序是一个可执行文件。
- 在编译项目时,会将 appsettings.json 文件复制到输出目录。
- 添加
Microsoft.Extensions.Hosting
NuGet 包引用。
在项目的根目录下添加具有以下内容的 appsettings.json 文件:
{
"KeyOne": 1,
"KeyTwo": true,
"KeyThree": {
"Message": "Thanks for checking this out!"
}
}
将 Program.cs 文件的内容替换为以下 C# 代码:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using IHost host = Host.CreateApplicationBuilder(args).Build();
// Ask the service provider for the configuration abstraction.
IConfiguration config = host.Services.GetRequiredService<IConfiguration>();
// Get values from the config given their key and their target type.
int keyOneValue = config.GetValue<int>("KeyOne");
bool keyTwoValue = config.GetValue<bool>("KeyTwo");
string? keyThreeNestedValue = config.GetValue<string>("KeyThree:Message");
// Write the values to the console.
Console.WriteLine($"KeyOne = {keyOneValue}");
Console.WriteLine($"KeyTwo = {keyTwoValue}");
Console.WriteLine($"KeyThree:Message = {keyThreeNestedValue}");
// Application code which might rely on the config could start here.
await host.RunAsync();
// This will output the following:
// KeyOne = 1
// KeyTwo = True
// KeyThree:Message = Thanks for checking this out!
运行此应用程序时,Host.CreateApplicationBuilder
定义了发现 JSON 配置并通过 IConfiguration
实例公开它的这样一个行为。 在 host
实例中,你可以向服务提供程序获取 IConfiguration
实例,然后向其获取值。
提示
以这种方式使用原始 IConfiguration
实例虽然方便,但不能很好地缩放。 当应用程序变得越来越复杂,其相应的配置也变得越来越复杂时,我们建议使用选项模式作为替代方法。
托管和使用索引器 API 的基本示例
请考虑前面示例中的相同 appsettings.json 文件内容:
{
"SupportedVersions": {
"v1": "1.0.0",
"v3": "3.0.7"
},
"IPAddressRange": [
"46.36.198.123",
"46.36.198.124",
"46.36.198.125"
]
}
将 Program.cs 文件的内容替换为以下 C# 代码:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using IHost host = Host.CreateApplicationBuilder(args).Build();
// Ask the service provider for the configuration abstraction.
IConfiguration config = host.Services.GetRequiredService<IConfiguration>();
// Get values from the config given their key and their target type.
string? ipOne = config["IPAddressRange:0"];
string? ipTwo = config["IPAddressRange:1"];
string? ipThree = config["IPAddressRange:2"];
string? versionOne = config["SupportedVersions:v1"];
string? versionThree = config["SupportedVersions:v3"];
// Write the values to the console.
Console.WriteLine($"IPAddressRange:0 = {ipOne}");
Console.WriteLine($"IPAddressRange:1 = {ipTwo}");
Console.WriteLine($"IPAddressRange:2 = {ipThree}");
Console.WriteLine($"SupportedVersions:v1 = {versionOne}");
Console.WriteLine($"SupportedVersions:v3 = {versionThree}");
// Application code which might rely on the config could start here.
await host.RunAsync();
// This will output the following:
// IPAddressRange:0 = 46.36.198.123
// IPAddressRange:1 = 46.36.198.124
// IPAddressRange:2 = 46.36.198.125
// SupportedVersions:v1 = 1.0.0
// SupportedVersions:v3 = 3.0.7
使用索引器 API 访问这些值,其中每个键都是字符串,值也是字符串。 配置支持属性、对象、数组和字典。
配置提供程序
下表显示了 .NET Core 应用可用的配置提供程序。
提供程序 | 通过以下对象提供配置 |
---|---|
Azure 应用配置提供程序 | Azure 应用程序配置 |
Azure Key Vault 配置提供程序 | Azure Key Vault |
命令行配置提供程序 | 命令行参数 |
自定义配置提供程序 | 自定义源 |
环境变量配置提供程序 | 环境变量 |
文件配置提供程序 | JSON、XML 和 INI 文件 |
Key-per-file 配置提供程序 | 目录文件 |
内存配置提供程序 | 内存中集合 |
应用机密(机密管理器) | 用户配置文件目录中的文件 |
提示
添加配置提供程序的顺序很重要。 使用多个配置提供程序,并且多个提供程序指定同一个键时,会使用最后添加的提供程序。
若要详细了解各种配置提供程序,请查看 .NET 中的配置提供程序。
另请参阅
- .NET 中的配置提供程序
- 实现自定义配置提供程序
- 配置 Bug 应在 github.com/dotnet/runtime 存储库中创建
- ASP.NET Core 中的配置