Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La configurazione in .NET viene eseguita usando uno o più provider di configurazione . I provider di configurazione leggono i dati di configurazione da coppie chiave-valore usando varie origini di configurazione:
- File di impostazioni, ad esempio appsettings.json
- Variabili di ambiente
- Azure Key Vault
- Configurazione App di Azure
- Argomenti della riga di comando
- Provider personalizzati (installati o creati)
- File della directory
- Oggetti .NET in memoria
- Fornitori di terze parti
Nota
Per informazioni sulla configurazione del runtime .NET stesso, vedere impostazioni di configurazione del runtime .NET.
Concetti e astrazioni
Data una o più origini di configurazione, il tipo IConfiguration fornisce una visualizzazione unificata dei dati di configurazione. La configurazione è di sola lettura e il modello di configurazione non è progettato per essere scrivibile a livello di codice. L'interfaccia IConfiguration è una singola rappresentazione di tutte le origini di configurazione, come illustrato nel diagramma seguente:
Configurare le applicazioni console
Le app console .NET create con il modello di comando dotnet new o Visual Studio di impostazione predefinita non espongono funzionalità di configurazione. Per aggiungere la configurazione in una nuova applicazione console .NET, aggiungere un riferimento al pacchetto a 📦 Microsoft.Extensions.Configuration. Questo pacchetto è la base per la configurazione nelle app .NET. Fornisce il ConfigurationBuilder e i tipi correlati.
using Microsoft.Extensions.Configuration;
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>()
{
["SomeKey"] = "SomeValue"
})
.Build();
Console.WriteLine(configuration["SomeKey"]);
// Outputs:
// SomeValue
Il codice precedente:
- Crea una nuova istanza di ConfigurationBuilder.
- Aggiunge una raccolta in memoria di coppie chiave-valore al generatore di configurazione.
- Chiama il metodo Build() per creare un'istanza di IConfiguration.
- Scrive il valore della chiave
SomeKeynella console.
Anche se in questo esempio viene usata una configurazione in memoria, sono disponibili molti provider di configurazione, che espongono funzionalità per le variabili di ambiente, gli argomenti della riga di comando e altre origini di configurazione basate su file. Per ulteriori informazioni, vedere i provider di configurazione in .NET.
Approccio alternativo all'hosting
In genere, le app eseguiranno più operazioni di sola lettura della configurazione. Probabilmente useranno il dependency injection, il logging e altri servizi. L'approccio host generico .NET è consigliato per le app che usano questi servizi. Prendere invece in considerazione l'aggiunta di un riferimento al pacchetto a 📦 Microsoft.Extensions.Hosting. Modificare il file Program.cs in modo che corrisponda al codice seguente:
using Microsoft.Extensions.Hosting;
using IHost host = Host.CreateApplicationBuilder(args).Build();
// Application code should start here.
await host.RunAsync();
Il metodo Host.CreateApplicationBuilder(String[]) fornisce la configurazione predefinita per l'app nell'ordine seguente, dalla priorità più alta alla più bassa:
- Argomenti della riga di comando che usano il provider di configurazione della riga di comando .
- Variabili di ambiente che usano il provider di configurazione delle variabili di ambiente .
-
I segreti dell'app quando l'app viene eseguita nell'ambiente
Development. -
appsettings.
Environment.json utilizzando il provider di configurazione JSON . Ad esempio, appsettings.Produzione.json e appsettings.Sviluppo.json. - appsettings.json usando il provider di configurazione JSON .
-
ChainedConfigurationProvider : aggiunge come origine un
IConfigurationesistente.
L'aggiunta di un provider di configurazione sostituisce i valori di configurazione precedenti. Ad esempio, il provider di configurazione della riga di comando sovrascrive tutti i valori provenienti da altri provider perché è stato aggiunto per ultimo. Se SomeKey è impostato sia in appsettings.json che nell'ambiente, il valore dell'ambiente viene usato perché è stato aggiunto dopo appsettings.json.
Vincolo
Uno dei vantaggi principali dell'uso delle astrazioni di configurazione .NET è la possibilità di associare valori di configurazione a istanze di oggetti .NET. Ad esempio, il provider di configurazione JSON può essere usato per eseguire il mapping dei file appsettings.json agli oggetti .NET e viene usato con l'inserimento delle dipendenze. Questo abilita il modello di opzioni , che usa le classi per fornire l'accesso fortemente tipizzato ai gruppi di impostazioni correlate. Il binder predefinito è basato sulla riflessione, ma c'è un'alternativa: il generatore di origine , facile da abilitare.
La configurazione di .NET fornisce diverse astrazioni. Si considerino le interfacce seguenti:
- IConfiguration: rappresenta un set di proprietà di configurazione dell'applicazione chiave/valore.
-
IConfigurationRoot: rappresenta la radice di una gerarchia di
IConfiguration. - IConfigurationSection: rappresenta una sezione dei valori di configurazione dell'applicazione.
Queste astrazioni sono indipendenti dal provider di configurazione sottostante (IConfigurationProvider). In altre parole, è possibile usare un'istanza di IConfiguration per accedere a qualsiasi valore di configurazione da più provider.
Il binder può usare approcci diversi per gestire i valori di configurazione.
- Deserializzazione diretta (usando convertitori predefiniti) per i tipi primitivi.
- Il TypeConverter per un tipo complesso quando il tipo ne ha uno.
- Reflection per un tipo complesso con proprietà.
Nota
Il binder presenta alcune limitazioni:
- Le proprietà vengono ignorate se dispongono di setter privati o se il tipo non può essere convertito.
- Le proprietà senza le chiavi di configurazione corrispondenti vengono ignorate.
Gerarchie di vincolo
I valori di configurazione possono contenere dati gerarchici. Gli oggetti gerarchici vengono rappresentati con l'uso del delimitatore : nelle chiavi di configurazione. Per accedere a un valore di configurazione, usare il carattere : per delimitare una gerarchia. Si considerino ad esempio i valori di configurazione seguenti:
{
"Parent": {
"FavoriteNumber": 7,
"Child": {
"Name": "Example",
"GrandChild": {
"Age": 3
}
}
}
}
La tabella seguente rappresenta le chiavi di esempio e i relativi valori corrispondenti per l'esempio JSON precedente:
| Chiave | Valore |
|---|---|
"Parent:FavoriteNumber" |
7 |
"Parent:Child:Name" |
"Example" |
"Parent:Child:GrandChild:Age" |
3 |
Scenari di associazione avanzati
Il binder di configurazione presenta comportamenti e limitazioni specifici quando si lavora con determinati tipi. Questa sezione include le seguenti sottosezioni:
- Associare ai dizionari
- Chiavi del dizionario con due punti
- Eseguire il binding ai tipi IReadOnly*
- Eseguire l'associazione con costruttori parametrizzati
Associare ai dizionari
Quando si associa la configurazione a un Dictionary<TKey,TValue> oggetto in cui il valore è un tipo di raccolta modificabile (ad esempio matrici o elenchi), le associazioni ripetute alla stessa chiave estendono i valori della raccolta anziché sostituirli.
L'esempio seguente illustra questo comportamento:
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"])}");
Per ulteriori informazioni, vedere Binding config to dictionary extends values.
Chiavi del dizionario con due punti
Il carattere due punti (:) è riservato come delimitatore di gerarchia nelle chiavi di configurazione. Ciò significa che non è possibile usare i due punti nelle chiavi del dizionario durante la configurazione dell'associazione. Se le tue chiavi contengono due punti (ad esempio URL o altri identificatori formattati), il sistema di configurazione le interpreta come percorsi della gerarchia anziché come caratteri letterali. Prendere in considerazione le soluzioni alternative seguenti:
- Usare caratteri delimitatori alternativi (ad esempio caratteri di sottolineatura doppia
__) nelle chiavi di configurazione e trasformarli in modo programmatico__, se necessario. - Deserializzare manualmente la configurazione come JSON non elaborato usando System.Text.Json o una libreria simile, che supporta i due punti nelle chiavi.
- Creare un livello di mapping personalizzato che converte le chiavi sicure nelle chiavi desiderate con i due punti.
Associare ai tipi IReadOnly*
Il gestore di associazione di configurazione non supporta l'associazione direttamente a IReadOnlyList<T>, IReadOnlyDictionary<TKey, TValue> o altre interfacce di raccolta di sola lettura. Queste interfacce non dispongono dei meccanismi necessari per popolare le raccolte.
Per usare le raccolte di sola lettura, utilizzare tipi modificabili per le proprietà che il binder popola, quindi esporle come interfacce di sola lettura per i consumer.
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}");
}
Implementazione della classe di configurazione:
class SettingsWithReadOnly
{
// Use mutable type for binding
public List<string> Values { get; set; } = [];
// Expose as read-only for consumers
public IReadOnlyList<string> ValuesReadOnly => Values;
}
Questo approccio consente al gestore di associazione di popolare la modificabile List<string> pur presentando un'interfaccia non modificabile agli utenti tramite IReadOnlyList<string>.
Associare con costruttori parametrizzati
A partire da .NET 7, il binder di configurazione supporta l'associazione ai tipi con un singolo costruttore pubblico con parametri. In questo modo, i tipi e i record non modificabili possono essere popolati direttamente dalla configurazione:
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}");
}
Classe di impostazioni non modificabili:
// 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;
}
}
Importante
Il binder supporta solo i tipi con un singolo costruttore con parametri pubblici. Se un tipo dispone di più costruttori con parametri pubblici, il binder non può determinare quale usare e l'associazione avrà esito negativo. Usare un singolo costruttore con parametri o un costruttore senza parametri con setter di proprietà.
Esempio di base
Per accedere ai valori di configurazione nel loro formato di base, senza l'assistenza dell'approccio host generico, utilizzare il tipo ConfigurationBuilder direttamente.
Suggerimento
Il tipo di System.Configuration.ConfigurationBuilder è diverso dal tipo di Microsoft.Extensions.Configuration.ConfigurationBuilder. Tutto questo contenuto è specifico per i pacchetti NuGet e gli spazi dei nomi Microsoft.Extensions.*.
Si consideri il progetto C# seguente:
<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>
Il file di progetto precedente fa riferimento a diversi pacchetti NuGet di configurazione:
-
Microsoft.Extensions.Configuration.Binder: funzionalità per associare un oggetto ai dati nei provider di configurazione per
Microsoft.Extensions.Configuration. -
Microsoft.Extensions.Configuration.Json: implementazione del provider di configurazione JSON per
Microsoft.Extensions.Configuration. -
Microsoft.Extensions.Configuration.EnvironmentVariables: implementazione del provider di configurazione delle variabili di ambiente per
Microsoft.Extensions.Configuration.
Si consideri un esempio di file 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"
]
}
}
Ora, dato questo file JSON, ecco un modello di utilizzo di esempio usando direttamente il generatore di configurazione:
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...
Il codice C# precedente:
- Crea un'istanza di ConfigurationBuilder.
- Aggiunge il file
"appsettings.json"da riconoscere dal provider di configurazione JSON. - Aggiunge le variabili di ambiente riconosciute dal provider di configurazione delle variabili di ambiente.
- Ottiene la sezione
"Settings"richiesta e l'istanza diSettingscorrispondente utilizzando l'istanza diconfig.
L'oggetto Settings viene modellato nel modo seguente:
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!;
}
Esempio di base con hosting
Per accedere al valore IConfiguration, è possibile fare di nuovo affidamento sul pacchetto NuGet Microsoft.Extensions.Hosting. Creare una nuova applicazione console e incollarvi il contenuto del file di progetto seguente:
<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>
Il file di progetto precedente definisce che:
- L'applicazione è un programma eseguibile.
- Un file appsettings.json deve essere copiato nella directory di output quando il progetto viene compilato.
- Viene aggiunto il riferimento al pacchetto NuGet
Microsoft.Extensions.Hosting.
Aggiungere il file appsettings.json alla radice del progetto con il contenuto seguente:
{
"KeyOne": 1,
"KeyTwo": true,
"KeyThree": {
"Message": "Thanks for checking this out!"
}
}
Sostituire il contenuto del file Program.cs con il codice C# seguente:
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!
Quando si esegue questa applicazione, il Host.CreateApplicationBuilder definisce il comportamento per individuare la configurazione JSON ed esporla tramite l'istanza di IConfiguration. Dall'istanza di host è possibile richiedere al provider di servizi l'istanza di IConfiguration e quindi richiedere i valori.
Suggerimento
L'uso dell'istanza grezza di IConfiguration in questo modo, sebbene conveniente, non si adatta molto bene. Quando le applicazioni aumentano di complessità e le configurazioni corrispondenti diventano più complesse, è consigliabile usare il modello di opzioni in alternativa.
Esempio di base con hosting e uso dell'API dell'indicizzatore
Si consideri lo stesso contenuto del file appsettings.json dell'esempio precedente:
{
"SupportedVersions": {
"v1": "1.0.0",
"v3": "3.0.7"
},
"IPAddressRange": [
"46.36.198.123",
"46.36.198.124",
"46.36.198.125"
]
}
Sostituire il contenuto del file Program.cs con il codice C# seguente:
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
È possibile accedere ai valori usando l'API dell'indicizzatore in cui ogni chiave è una stringa e il valore è una stringa. La configurazione supporta proprietà, oggetti, matrici e dizionari.
Provider di configurazione
La tabella seguente illustra i provider di configurazione disponibili per le app .NET Core.
| Provider di configurazione | Fornisce la configurazione da |
|---|---|
| Configurazione App di Azure | Configurazione app di Azure |
| Azure Key Vault | Azure Key Vault (Archivio chiavi di Azure) |
| Riga di comando | Parametri della riga di comando |
| Personalizzato | Origine personalizzata |
| Variabili di ambiente | Variabili di ambiente |
| File | File JSON, XML e INI |
| Key-per-file | File della directory |
| Memory | Collezioni in memoria |
| Segreti dell'app (secret manager) | File nella directory del profilo utente |
Suggerimento
L'ordine in cui vengono aggiunti i provider di configurazione è importante. Quando vengono usati più provider di configurazione e più provider specificano la stessa chiave, viene usata l'ultima aggiunta.
Per ulteriori informazioni sui vari provider di configurazione, consultare Configuration providers in .NET.
Vedere anche
- provider di configurazione in .NET
- Implementare un provider di configurazione personalizzato
- I bug di configurazione devono essere creati nel repository github.com/dotnet/runtime
- La configurazione in ASP.NET Core