.NET 中的組態是使用一或多個 組態提供者來執行,。 設定提供者使用各種設定來源,從鍵值對讀取設定資料。
- 配置檔案,例如 appsettings.json
- 環境變數
- Azure 密鑰保管庫
- Azure 應用程式組態
- 命令列參數
- 自訂供應商(已安裝或建立)
- 目錄檔案
- 記憶體內部 .NET 物件
- 第三方提供者
注意
如需設定 .NET 執行時間本身的相關信息,請參閱 .NET 執行時間組態設定。
概念和抽象概念
假設有一或多個組態來源,IConfiguration 類型會提供組態數據的統一檢視。 組態是只讀的,而且設定模式的設計不是以程式設計方式可寫入的。
IConfiguration 介面是所有組態來源的單一表示法,如下圖所示:
設定主控台應用程式
使用 dotnet 新 指令範本或 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環境中執行時。 -
appsettings.
Environment.json 使用 JSON 設定提供者。 例如,appsettings。Production。json 和 appsettings。Development。json。 - appsettings.json 使用 JSON 組態提供者。
-
ChainedConfigurationProvider:將現有的
IConfiguration新增為來源。
新增設定提供程式會覆寫先前的組態值。 例如,命令列組態提供者 會覆寫其他提供者的所有值,因為它是最後添加的。 如果在 SomeKey 和環境中設定 ,則會使用環境值,因為已在 appsettings.json之後新增它。
捆綁
使用 .NET 配置抽象的一大優勢是能夠將設定值 綁定 到 .NET 物件的實例。 例如,JSON 組態提供者可用來將 appsettings.json 檔案對應至 .NET 物件,並與 相依性插入搭配使用。 這可讓 選項設計模式,並且此模式使用類別來提供強型別存取,允許存取相關的設定群組。 默認系結器是基於反射的,但還有一個易於啟用的 來源產生器替代方案。
.NET 組態提供各種抽象概念。 請考慮下列介面:
- IConfiguration:代表一組鍵/值的應用程式配置屬性。
-
IConfigurationRoot:代表
IConfiguration階層的根基。 - IConfigurationSection:代表應用程式組態值的區段。
這些抽象概念與其基礎組態提供者無關(IConfigurationProvider)。 換句話說,您可以使用 IConfiguration 實例,從多個提供者存取任何組態值。
系結器可以使用不同的方法來處理組態值:
- 基本型別的直接反序列化,使用內建轉換器。
- 當類型存在一個複雜型別時,其複雜型別的 TypeConverter。
- 具有屬性之複雜類型的反映。
注意
系結器有一些限制:
- 如果屬性具有 private 設定器,或其類型無法轉換,則會忽略該屬性。
- 忽略沒有對應組態索引鍵的屬性。
系結階層
組態值可以包含階層式數據。 階層式物件會使用組態索引鍵中的 : 分隔符來表示。 若要存取組態值,請使用 : 字元來分隔階層。 例如,請考慮下列組態值:
{
"Parent": {
"FavoriteNumber": 7,
"Child": {
"Name": "Example",
"GrandChild": {
"Age": 3
}
}
}
}
下表代表上述範例 JSON 的範例索引鍵及其對應的值:
| 鑰匙 | 價值 |
|---|---|
"Parent:FavoriteNumber" |
7 |
"Parent:Child:Name" |
"Example" |
"Parent:Child:GrandChild:Age" |
3 |
進階綁定情境
配置綁定器在處理特定類型時有特定的行為與限制。 本節包含下列子區段:
綁定到字典
當您將設定綁定到值為可變集合類型(例如陣列或清單)時,重複綁定到相同的鍵會擴展集合中的值,而不是替換它們。
下列範例示範此行為:
IConfiguration config = new ConfigurationBuilder()
.AddInMemoryCollection()
.Build();
config["Queue:0"] = "Value1";
var dict = new Dictionary<string, string[]>() { { "Queue", new[] { "InitialValue" } } };
Console.WriteLine("=== Dictionary Binding with Collection Values ===");
Console.WriteLine($"Initially: {string.Join(", ", dict["Queue"])}");
// In .NET 7+, binding extends the collection instead of replacing it.
config.Bind(dict);
Console.WriteLine($"After Bind: {string.Join(", ", dict["Queue"])}");
config["Queue:1"] = "Value2";
config.Bind(dict);
Console.WriteLine($"After 2nd Bind: {string.Join(", ", dict["Queue"])}");
更多資訊請參見 「綁定設定到字典擴充值」。
帶有冒號的字典鍵
冒號(:)字元保留為組態鍵中的階層分隔符。 這表示你在綁定設定時不能在字典鍵中使用冒號。 如果你的金鑰包含冒號(例如 URL 或其他格式化識別碼),設定系統會將它們解讀為階層路徑,而非字元。 請考慮以下的變通方法:
- 在配置鍵中使用替代的分隔字元(例如雙重底線
__),必要時用程式化轉換。 - 手動使用 System.Text.Json 或類似函式庫,將設定解序列化為原始 JSON,這些函式庫支援鍵中使用冒號。
- 建立一個自訂的映射圖層,將安全金鑰轉換成你想要的金鑰,並加冒號。
綁定 IReadOnly* 類型
設定綁定器不支援直接綁定到 IReadOnlyList<T>、IReadOnlyDictionary<TKey, TValue>,或其他唯讀的集合介面。 這些介面缺乏绑定器所需的機制來填充集合。
若要處理唯讀集合,請使用可變型別來設定裝訂器會填充的屬性,然後將這些屬性以唯讀介面的形式公開給消費者:
Console.WriteLine("=== IReadOnly* Types (NOT Directly Supported) ===");
var readonlyConfig = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Settings:Values:0"] = "Item1",
["Settings:Values:1"] = "Item2",
["Settings:Values:2"] = "Item3",
})
.Build();
// This class uses List<string> for binding, exposes as IReadOnlyList<string>.
var settings = new SettingsWithReadOnly();
readonlyConfig.GetSection("Settings").Bind(settings);
Console.WriteLine("Values bound to mutable List, exposed as IReadOnlyList:");
foreach (var value in settings.ValuesReadOnly)
{
Console.WriteLine($" {value}");
}
組態類別實作:
class SettingsWithReadOnly
{
// Use mutable type for binding
public List<string> Values { get; set; } = [];
// Expose as read-only for consumers
public IReadOnlyList<string> ValuesReadOnly => Values;
}
此方法允許綁定器在透過IReadOnlyList<string>向消費者呈現不可變介面的同時,填充可變List<string>物件。
與參數化建構子綁定
從 .NET 7 開始,配置繫結器支援綁定到具有單一公開參數化建構子的型別。 這使得不可變型別與紀錄能直接從設定中填充:
Console.WriteLine("=== Parameterized Constructor Binding ===");
var ctorConfig = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["AppSettings:Name"] = "MyApp",
["AppSettings:MaxConnections"] = "100",
["AppSettings:Timeout"] = "30"
})
.Build();
// Binding to a type with a single parameterized constructor
var appSettings = ctorConfig.GetSection("AppSettings").Get<AppSettings>();
if (appSettings != null)
{
Console.WriteLine($"Name: {appSettings.Name}");
Console.WriteLine($"MaxConnections: {appSettings.MaxConnections}");
Console.WriteLine($"Timeout: {appSettings.Timeout}");
}
不變設定類別:
// Immutable type with single parameterized constructor.
class AppSettings
{
public string Name { get; }
public int MaxConnections { get; }
public int Timeout { get; }
public AppSettings(string name, int maxConnections, int timeout)
{
Name = name;
MaxConnections = maxConnections;
Timeout = timeout;
}
}
這很重要
該綁定器僅支援具有單一公開參數化建構子的型別。 如果一個型別有多個公開參數化建構子,綁定器無法決定使用哪一個,綁定將失敗。 使用單一參數化建構子或無參數建構器,並使用屬性設定器。
基本範例
若要以基本形式存取組態值,如果沒有 一般主機 方法的協助,請直接使用 ConfigurationBuilder 類型。
提示
System.Configuration.ConfigurationBuilder 類型與 Microsoft.Extensions.Configuration.ConfigurationBuilder 類型不同。 此內容全都專屬於 Microsoft.Extensions.* NuGet 套件和命名空間。
請考慮下列 C# 專案:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.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="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.3" />
</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 組態提供者辨識。 - 將環境變數新增以供環境變數組態提供者辨識。
- 使用
"Settings"實例,取得所需的Settings區段和相應的config實例。
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>net10.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="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.3" />
</ItemGroup>
</Project>
上述項目檔會定義:
- 應用程式是可執行檔。
- 編譯專案時,appsettings.json 檔案會複製到輸出目錄。
- 已新增
Microsoft.Extensions.HostingNuGet 套件參考。
使用下列內容,在專案的根目錄中新增 appsettings.json 檔案:
{
"KeyOne": 1,
"KeyTwo": true,
"KeyThree": {
"Message": "Thanks for checking this out!"
}
}
使用下列 C# 程式代碼取代 Program.cs 檔案的內容:
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"
]
}
使用下列 C# 程式代碼取代 Program.cs 檔案的內容:
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 密鑰保管庫 | Azure Key Vault |
| 命令列 | 命令行參數 |
| 自定義 | 自訂來源 |
| 環境變數 | 環境變數 |
| File | JSON、XML 和 INI 檔案 |
| 每個檔案的鍵 | 目錄檔案 |
| 記憶體 | 內存集合 |
| 應用程式秘密(秘密管理器) | 使用者配置檔目錄中的檔案 |
提示
新增組態提供者的順序很重要。 使用多個組態提供者,且多個提供者指定相同的索引鍵時,會使用最後一個新增的密鑰。
如需各種組態提供者的詳細資訊,請參閱 .NET 中的組態提供者。
另請參閱
- .NET 中的 組態提供者
- 實作自定義組態提供者
- 應該在 github.com/dotnet/runtime 存放庫中建立組態錯誤
- ASP.NET Core 中的 組態