.NET 中的配置提供程序

可通过配置提供程序进行 .NET 配置。 有几种类型的提供程序依赖于不同的配置源。 本文详细介绍了所有不同的配置提供程序及其相应的源。

文件配置提供程序

FileConfigurationProvider 是从文件系统加载配置的基类。 以下配置提供程序派生自 FileConfigurationProvider

键不区分大小写。 单个提供程序中发现重复的键时,所有文件配置提供程序都会引发 FormatException

JSON 配置提供程序

JsonConfigurationProvider 类从 JSON 文件加载配置。 安装 Microsoft.Extensions.Configuration.Json NuGet 包。

重载可以指定:

  • 文件是否可选。
  • 如果文件更改,是否重载配置。

考虑下列代码:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ConsoleJson.Example;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Configuration.Sources.Clear();

IHostEnvironment env = builder.Environment;

builder.Configuration
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);

TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
    .Bind(options);

Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");

using IHost host = builder.Build();

// Application code should start here.

await host.RunAsync();

前面的代码:

  • 清除 CreateApplicationBuilder(String[]) 方法中默认添加的所有现有的配置提供程序。
  • 将 JSON 配置提供程序配置为使用以下选项加载 appsettings.json 和 appsettings.Environment.json 文件
    • optional: true:文件是可选的。
    • reloadOnChange: true:保存更改后会重载文件。

重要

当使用 IConfigurationBuilder.Add添加配置提供程序时,添加的配置提供程序会添加到 IConfigurationSource 列表的末尾。 当多个提供程序找到密钥时,读取密钥的最后一个提供程序将替代之前的提供程序。

下面是一个具有各种配置设置的示例 appsettings.json 文件:

{
    "SecretKey": "Secret key value",
    "TransientFaultHandlingOptions": {
        "Enabled": true,
        "AutoRetryDelay": "00:00:07"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    }
}

IConfigurationBuilder 实例中,在添加配置提供程序后,可调用 IConfigurationBuilder.Build() 来获取 IConfigurationRoot 对象。 配置根表示配置层次结构的根。 可将配置中的节绑定到 .NET 对象的实例,稍后再通过依赖注入将其作为 IOptions<TOptions> 提供。

备注

JSON 文件的“生成操作”和“复制到输出目录”属性必须分别设置为“内容”和“如果更新则复制”(或“始终复制”)。

请考虑如下定义的 TransientFaultHandlingOptions 类:

namespace ConsoleJson.Example;

public sealed class TransientFaultHandlingOptions
{
    public bool Enabled { get; set; }
    public TimeSpan AutoRetryDelay { get; set; }
}

下面的代码会生成配置根,将一个节绑定到类 TransientFaultHandlingOptions 类型,并将绑定值输出到控制台窗口:

TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
    .Bind(options);

Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");

应用程序编写以下示例输出:

// Sample output:
//    TransientFaultHandlingOptions.Enabled=True
//    TransientFaultHandlingOptions.AutoRetryDelay=00:00:07

XML 配置提供程序

XmlConfigurationProvider 类在运行时从 XML 文件加载配置。 安装 Microsoft.Extensions.Configuration.Xml NuGet 包。

下面的代码演示如何使用 XML 配置提供程序配置 XML 文件。

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Configuration.Sources.Clear();

builder.Configuration
    .AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true)
    .AddXmlFile("repeating-example.xml", optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();

if (args is { Length: > 0 })
{
    builder.Configuration.AddCommandLine(args);
}

using IHost host = builder.Build();

// Application code should start here.

await host.RunAsync();

前面的代码:

  • 清除 CreateApplicationBuilder(String[]) 方法中默认添加的所有现有的配置提供程序。
  • 将 XML 配置提供程序配置为使用以下选项加载 appsettings.xml 和 repeating-example.xml 文件
    • optional: true:文件是可选的。
    • reloadOnChange: true:保存更改后会重载文件。
  • 配置环境变量配置提供程序。
  • 如果给定的 args 包含自变量,则配置命令行配置提供程序。

XML 设置会被环境变量配置提供程序命令行配置提供程序中的设置替代。

下面是一个具有各种配置设置的示例 appsettings.xml 文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <SecretKey>Secret key value</SecretKey>
  <TransientFaultHandlingOptions>
    <Enabled>true</Enabled>
    <AutoRetryDelay>00:00:07</AutoRetryDelay>
  </TransientFaultHandlingOptions>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

提示

若要在 WinForms 应用中使用 IConfiguration 类型,请添加对 Microsoft.Extensions.Configuration.Xml NuGet 包的引用。 实例化 ConfigurationBuilder 并将调用链接到 AddXmlFileBuild()。 有关详细信息,请参阅 .NET 文档问题 #29679

在 .NET 5 及更早版本中,添加 name 属性以区分使用同一元素名称的重复元素。 在 .NET 6 及更高版本中,XML 配置提供程序会自动为重复元素编制索引。 这意味着你不必指定 name 属性,除非你希望键中有“0”索引,并且只有一个元素。 (如果要升级到 .NET 6 或更高版本,可能会遇到此行为更改导致的中断。有关详细信息,请参阅重复的 XML 元素包括索引。)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section name="section0">
    <key name="key0">value 00</key>
    <key name="key1">value 01</key>
  </section>
  <section name="section1">
    <key name="key0">value 10</key>
    <key name="key1">value 11</key>
  </section>
</configuration>

以下代码会读取前面的配置文件并显示键和值:

IConfigurationRoot configurationRoot = builder.Configuration;

string key00 = "section:section0:key:key0";
string key01 = "section:section0:key:key1";
string key10 = "section:section1:key:key0";
string key11 = "section:section1:key:key1";

string? val00 = configurationRoot[key00];
string? val01 = configurationRoot[key01];
string? val10 = configurationRoot[key10];
string? val11 = configurationRoot[key11];

Console.WriteLine($"{key00} = {val00}");
Console.WriteLine($"{key01} = {val01}");
Console.WriteLine($"{key10} = {val10}");
Console.WriteLine($"{key10} = {val11}");

该应用程序会编写以下示例输出:

// Sample output:
//    section:section0:key:key0 = value 00
//    section:section0:key:key1 = value 01
//    section:section1:key:key0 = value 10
//    section:section1:key:key0 = value 11

属性可用于提供值:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

以前的配置文件使用 value 加载以下键:

  • key:attribute
  • section:key:attribute

INI 配置提供程序

IniConfigurationProvider 类在运行时从 INI 文件加载配置。 安装 Microsoft.Extensions.Configuration.Ini NuGet 包。

以下代码将清除所有配置提供程序,并添加具有两个 INI 文件的 IniConfigurationProvider 作为源:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Configuration.Sources.Clear();

IHostEnvironment env = builder.Environment;

builder.Configuration
    .AddIniFile("appsettings.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"appsettings.{env.EnvironmentName}.ini", true, true);

using IHost host = builder.Build();

// Application code should start here.

await host.RunAsync();

下面是一个具有各种配置设置的示例 appsettings.ini 文件:

SecretKey="Secret key value"

[TransientFaultHandlingOptions]
Enabled=True
AutoRetryDelay="00:00:07"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

以下代码通过将上述配置设置写入控制台窗口来显示这些设置:

foreach ((string key, string? value) in
    builder.Configuration.AsEnumerable().Where(t => t.Value is not null))
{
    Console.WriteLine($"{key}={value}");
}

该应用程序会编写以下示例输出:

// Sample output:
//    TransientFaultHandlingOptions:Enabled=True
//    TransientFaultHandlingOptions:AutoRetryDelay=00:00:07
//    SecretKey=Secret key value
//    Logging:LogLevel:Microsoft=Warning
//    Logging:LogLevel:Default=Information

环境变量配置提供程序

通过默认配置,EnvironmentVariablesConfigurationProvider 会在读取 appsettings.json、appsettings..json 和机密管理器后,从环境变量键值对加载配置。 因此,从环境中读取的键值会替代从 appsettings.json、appsettings..json 和机密管理器中读取的值。

所有平台上的环境变量分层键都不支持 : 分隔符。 例如,Bash 不支持 : 分隔符。 在所有平台上都受支持的双下划线 (__) 会自动替换环境变量中的任何 : 分隔符。

请考虑使用 TransientFaultHandlingOptions 类:

public class TransientFaultHandlingOptions
{
    public bool Enabled { get; set; }
    public TimeSpan AutoRetryDelay { get; set; }
}

以下 set 命令设置环境键以及 SecretKeyTransientFaultHandlingOptions 的值。

set SecretKey="Secret key from environment"
set TransientFaultHandlingOptions__Enabled="true"
set TransientFaultHandlingOptions__AutoRetryDelay="00:00:13"

这些环境设置仅在进程中设置,这些进程是从设置进程的命令窗口启动的。 它们不会由通过 Visual Studio 启动的 Web 应用读取。

在 Visual Studio 2019 版本及更高版本中,可以使用“启动配置文件”对话框指定环境变量。

Launch Profiles dialog showing environment variables

以下 setx 命令可用于在 Windows 上设置环境键和值。 与 set 不同,setx 设置是持久的。 /M 在系统环境中设置变量。 如果未使用 /M 开关,则会设置用户环境变量。

setx SecretKey "Secret key from setx environment" /M
setx TransientFaultHandlingOptions__Enabled "true" /M
setx TransientFaultHandlingOptions__AutoRetryDelay "00:00:05" /M

测试前面的命令是否会替代任何 appsettings.json 和 appsettings.Environment.json 设置:

  • 使用 Visual Studio:退出并重启 Visual Studio。
  • 使用 CLI:启动新的命令窗口并输入 dotnet run

前缀

若要指定环境变量的前缀,请使用字符串调用 AddEnvironmentVariables

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Configuration.AddEnvironmentVariables(prefix: "CustomPrefix_");

using IHost host = builder.Build();

// Application code should start here.

await host.RunAsync();

在上述代码中:

  • config.AddEnvironmentVariables(prefix: "CustomPrefix_") 被添加到默认配置提供程序的后面。 有关对配置提供程序进行排序的示例,请查看 XML 配置提供程序
  • 设有 CustomPrefix_ 前缀的环境变量会替代默认配置提供程序。 这包括没有前缀的环境变量。

前缀会在读取配置键值对时被去除。

默认配置会加载前缀为 DOTNET_ 的环境变量和命令行自变量。 DOTNET_ 前缀由 .NET 用于DOTNET_应用配置,但不用于用户配置。

有关主机和应用配置的详细信息,请参阅 .NET 通用主机

连接字符串前缀

对于四个连接字符串环境变量,配置 API 具有特殊的处理规则。 这些连接字符串涉及了为应用环境配置 Azure 连接字符串。 使用默认配置或没有向 AddEnvironmentVariables 应用前缀时,具有表中所示前缀的环境变量将加载到应用中。

连接字符串前缀 提供程序
CUSTOMCONNSTR_ 自定义提供程序
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ Azure SQL 数据库
SQLCONNSTR_ SQL Server

当发现环境变量并使用表中所示的四个前缀中的任何一个加载到配置中时:

  • 通过删除环境变量前缀并添加配置键节 (ConnectionStrings) 来创建配置键。
  • 创建一个新的配置键值对,表示数据库连接提供程序(CUSTOMCONNSTR_ 除外,它没有声明的提供程序)。
环境变量键 转换的配置键 提供程序配置条目
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} 配置条目未创建。
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} 键:ConnectionStrings:{KEY}_ProviderName
值:MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} 键:ConnectionStrings:{KEY}_ProviderName
值:System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} 键:ConnectionStrings:{KEY}_ProviderName
值:System.Data.SqlClient

在 launchSettings.json 中设置的环境变量

在 launchSettings.json 中设置的环境变量将替代在系统环境中设置的变量。

Azure 应用服务设置

Azure 应用服务上,选择“设置”>“配置”页上的“新应用程序设置”。 Azure 应用服务应用程序设置:

  • 已静态加密且通过加密的通道进行传输。
  • 已作为环境变量公开。

命令行配置提供程序

使用默认配置,CommandLineConfigurationProvider 会从以下配置源后的命令行参数键值对中加载配置:

  • appsettings.json 和 appsettings..json 文件。
  • Development 环境中的应用机密(机密管理器)。
  • 环境变量。

默认情况下,在命令行上设置的配置值会替代通过所有其他配置提供程序设置的配置值。

在 Visual Studio 2019 版本及更高版本中,可以使用“启动配置文件”对话框指定命令行参数。

Launch Profiles dialog showing command-line arguments

命令行参数

以下命令使用 = 设置键和值:

dotnet run SecretKey="Secret key from command line"

以下命令使用 / 设置键和值:

dotnet run /SecretKey "Secret key set from forward slash"

以下命令使用 -- 设置键和值:

dotnet run --SecretKey "Secret key set from double hyphen"

键值:

  • 必须后跟 =,或者当值后跟一个空格时,键必须具有一个 --/ 的前缀。
  • 如果使用 =,则不是必需的。 例如 SomeKey=

在同一命令中,请勿将使用 = 的命令行参数键值对与使用空格的键值对混合使用。

Key-per-file 配置提供程序

KeyPerFileConfigurationProvider 使用目录的文件作为配置键值对。 该键是文件名。 该值是文件的内容。 Key-per-file 配置提供程序用于 Docker 托管方案。

若要激活 Key-per-file 配置,请在 ConfigurationBuilder 的实例上调用 AddKeyPerFile 扩展方法。 文件的 directoryPath 必须是绝对路径。

重载允许指定:

  • 配置源的 Action<KeyPerFileConfigurationSource> 委托。
  • 目录是否可选以及目录的路径。

双下划线字符 (__) 用作文件名中的配置键分隔符。 例如,文件名 Logging__LogLevel__System 生成配置键 Logging:LogLevel:System

构建主机时调用 ConfigureAppConfiguration 以指定应用的配置:

.ConfigureAppConfiguration((_, configuration) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");

    configuration.AddKeyPerFile(directoryPath: path, optional: true);
})

内存配置提供程序

MemoryConfigurationProvider 使用内存中集合作为配置键值对。

以下代码将内存集合添加到配置系统中:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Configuration.AddInMemoryCollection(
    new Dictionary<string, string?>
    {
        ["SecretKey"] = "Dictionary MyKey Value",
        ["TransientFaultHandlingOptions:Enabled"] = bool.TrueString,
        ["TransientFaultHandlingOptions:AutoRetryDelay"] = "00:00:07",
        ["Logging:LogLevel:Default"] = "Warning"
    });

using IHost host = builder.Build();

// Application code should start here.

await host.RunAsync();

在上述代码中,MemoryConfigurationBuilderExtensions.AddInMemoryCollection(IConfigurationBuilder, IEnumerable<KeyValuePair<String,String>>) 会在默认配置提供程序之后添加内存提供程序。 有关对配置提供程序进行排序的示例,请查看 XML 配置提供程序

另请参阅