Konfiguration in .NET

Die Konfiguration in .NET erfolgt mithilfe eines oder mehrerer Konfigurationsanbieter. Konfigurationsanbieter lesen Konfigurationsdaten unter Verwendung verschiedener Konfigurationsquellen aus Schlüssel-Wert-Paaren:

  • Einstellungsdateien, z. B. appsettings.json
  • Umgebungsvariablen
  • Azure Key Vault
  • Azure App Configuration
  • Befehlszeilenargumente
  • Benutzerdefinierte Anbieter (installiert oder erstellt)
  • Verzeichnisdateien
  • Speicherinterne .NET Objekte
  • Drittanbieter

Hinweis

Informationen zum Konfigurieren der .NET Runtime selbst finden Sie unter Konfigurationseinstellungen für .NET Runtime.

Konzepte und Abstraktionen

Bei einer oder mehreren Konfigurationsquellen stellt der Typ IConfiguration eine einheitliche Ansicht der Konfigurationsdaten bereit. Die Konfiguration ist schreibgeschützt, und das Konfigurationsmuster kann nicht programmgesteuert geschrieben werden. Die Schnittstelle IConfiguration ist eine einzelne Repräsentation aller Konfigurationsquellen, wie im folgenden Diagramm dargestellt:

The `IConfiguration` interface is a single representation of all the configuration sources.

Konfigurieren von Konsolen-Apps

.NET-Konsolenanwendungen, die mit der Befehlsvorlage dotnet new oder mit Visual Studio erstellt werden, machen standardmäßig keine Konfigurationsfunktionen verfügbar. Um Konfigurationsmöglichkeiten in einer neuen .NET-Konsolenanwendung hinzuzufügen, müssen Sie Microsoft.Extensions.Configuration einen Paketverweis hinzufügen. Dieses Paket ist die Grundlage für die Konfiguration in .NET-Apps. Sie stellt den ConfigurationBuilder und verwandte Typen bereit.

using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
    .AddInMemoryCollection(new Dictionary<string, string?>()
    {
        ["SomeKey"] = "SomeValue"
    })
    .Build();

Console.WriteLine(configuration["SomeKey"]);

// Outputs:
//   SomeValue

Der vorangehende Code:

  • Erstellt eine neue ConfigurationBuilder-Instanz.
  • Fügt dem Konfigurations-Generator eine Speicherauflistung von Schlüssel-Wert-Paaren hinzu.
  • Ruft die Build()-Methode auf, um eine IConfiguration-Instanz zu erstellen.
  • Gibt den Wert des Schlüssels SomeKey an der Konsole aus.

In diesem Beispiel wird zwar eine Konfiguration im Arbeitsspeicher verwendet, es gibt jedoch zahlreiche Konfigurationsanbieter, die Funktionen für dateibasierte Konfigurationsquellen, Umgebungsvariablen, Befehlszeilenargumente u. v. m. verfügbar machen. Weitere Informationen finden Sie unter Konfigurationsanbieter in .NET.

Alternativer Hostingansatz

Häufig erledigen Ihre Apps mehr als nur die Lesekonfiguration. Sie werden wahrscheinlich Abhängigkeitsinjektionen, Protokollierung und andere Dienste verwenden. Für Apps, die diese Dienste verwenden, wird der Ansatz mit generischem .NET-Host empfohlen. Erwägen Sie stattdessen das Hinzufügen eines Paketverweises in Microsoft.Extensions.Hosting. Ändern Sie die Program.cs-Datei so, dass Sie dem folgenden Code entspricht:

using Microsoft.Extensions.Hosting;

using IHost host = Host.CreateApplicationBuilder(args).Build();

// Application code should start here.

await host.RunAsync();

Die Methode Host.CreateApplicationBuilder(String[]) legt die Standardkonfiguration für die App in der folgenden Reihenfolge fest, von der höchsten zur niedrigsten Priorität:

  1. Befehlszeilenargumente, die den Befehlszeilen-Konfigurationsanbieter verwenden
  2. Umgebungsvariablen, die den Umgebungsvariablen-Konfigurationsanbieter verwenden
  3. App-Geheimnisse, wenn die App in der Development-Umgebung ausgeführt wird
  4. appsettings.json mithilfe des JSON-Konfigurationsanbieters.
  5. appsettings.Environment.json mithilfe des JSON-Konfigurationsanbieters. Beispiel: „appsettings.Production.json“ und „appsettings.Development.json“.
  6. ChainedConfigurationProvider: Fügt eine vorhandene IConfiguration als Quelle hinzu.

Durch Hinzufügen eines Konfigurationsanbieters werden vorherige Konfigurationswerte überschrieben. Beispielsweise überschreibt der Befehlszeilen-Konfigurationsanbieter alle Werte von anderen Anbietern, da er zuletzt hinzugefügt wurde. Wenn SomeKey sowohl in appsettings.json als auch in der Umgebung festgelegt ist, wird der Umgebungswert verwendet, da dieser nach appsettings.json hinzugefügt wurde.

Bindung

Einer der Hauptvorteile der Verwendung der .NET-Konfigurationsabstraktionen ist die Möglichkeit, Konfigurationswerte an Instanzen von .NET-Objekten zu binden. JSON-Konfigurationsanbieter können zum Beispiel verwendet werden, um appsettings.json-Dateien .NET-Objekten zuzuordnen, und sie werden mit Abhängigkeitsinjektion verwendet. Damit wird das Optionsmuster aktiviert. Dieses verwendet Klassen, um stark typisierten Zugriff auf zusammengehörige Einstellungsgruppen zu ermöglichen. Die .NET-Konfiguration bietet verschiedene Abstraktionen. Betrachten Sie die folgenden Schnittstellen:

Diese Abstraktionen sind unabhängig von ihrem zugrunde liegenden Konfigurationsanbieter (IConfigurationProvider). Anders ausgedrückt: Sie können eine IConfiguration-Instanz verwenden, um auf jeden Konfigurationswert von mehreren Anbietern zuzugreifen.

Der Binder kann Konfigurationswerte auf unterschiedliche Weise verarbeiten:​

  • Direkte Deserialisierung (mithilfe integrierter Konverter) für primitive Typen.
  • Mit dem TypeConverter für einen komplexen Typ, sofern der Typ über einen solchen verfügt.
  • Reflexion für einen komplexen Typ mit Eigenschaften.

Hinweis

Für den Binder gelten einige Einschränkungen:

  • Eigenschaften werden ignoriert, wenn sie private Setter haben oder ihr Typ nicht konvertiert werden kann.
  • Eigenschaften ohne entsprechende Konfigurationsschlüssel werden ignoriert.

Bindungshierarchien

Konfigurationswerte können hierarchische Daten enthalten. Hierarchische Objekte werden unter Verwendung des Trennzeichens : in den Konfigurationsschlüsseln dargestellt. Um auf einen Konfigurationswert zuzugreifen, verwenden Sie das Zeichen : zum Trennen von Hierarchiewerten. Sehen Sie sich beispielsweise die folgenden Konfigurationswerte an:

{
  "Parent": {
    "FavoriteNumber": 7,
    "Child": {
      "Name": "Example",
      "GrandChild": {
        "Age": 3
      }
    }
  }
}

Die folgende Tabelle stellt Beispielschlüssel und die entsprechenden Werte für die vorangehende Beispiel-JSON dar:

Schlüssel Wert
"Parent:FavoriteNumber" 7
"Parent:Child:Name" "Example"
"Parent:Child:GrandChild:Age" 3

Einfaches Beispiel

Um auf Konfigurationswerte in ihrer Grundform zuzugreifen – ohne Unterstützung des Ansatzes mit einem generischen Host –, verwenden Sie den Typ ConfigurationBuilder direkt.

Tipp

Der Typ System.Configuration.ConfigurationBuilder unterscheidet sich vom Typ Microsoft.Extensions.Configuration.ConfigurationBuilder. Alle diese Inhalte sind spezifisch für die Microsoft.Extensions.*-NuGet-Pakete und -Namespaces.

Sehen Sie sich folgenden C#-Projekt an:

<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.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
  </ItemGroup>

</Project>

Die Projektdatei oben verweist auf mehrere NuGet-Konfigurationspakete:

Sehen Sie sich eine Datei appsettings.json an:

{
    "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"
        ]
    }
}

Hier finden Sie ein Beispiel für ein Nutzungsmuster, das den Konfigurations-Generator anhand dieser JSON-Datei direkt verwendet:

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...

Für den C#-Code oben gilt:

  • Er instanziiert ConfigurationBuilder.
  • Er fügt die "appsettings.json"-Datei hinzu, die vom JSON-Konfigurationsanbieter erkannt werden soll.
  • Er fügt Umgebungsvariablen hinzu, die vom Umgebungsvariablen-Konfigurationsanbieter erkannt werden sollen.
  • Ruft den erforderlichen "Settings"-Abschnitt und die entsprechende Settings-Instanz mithilfe der config-Instanz ab.

Das Settings-Objekt ist wie folgt geformt:

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!;
}

Einfaches Beispiel mit Hosting

Um auf den IConfiguration-Wert zu zugreifen, können Sie erneut das NuGet-Paket Microsoft.Extensions.Hosting verwenden. Erstellen Sie eine neue Konsolenanwendung, und fügen Sie die folgenden Projektdateiinhalte ein:

<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.Hosting" Version="8.0.0" />
  </ItemGroup>

</Project>

Die obige Projektdatei definiert Folgendes:

  • Die Anwendung ist eine ausführbare Datei.
  • Eine appsettings.json-Datei soll beim Kompilieren des Projekts in das Ausgabeverzeichnis kopiert werden.
  • Der NuGet-Paketverweis Microsoft.Extensions.Hosting wird hinzugefügt.

Fügen Sie die appsettings.json-Datei im Stammverzeichnis des Projekts mit folgendem Inhalt hinzu:

{
    "KeyOne": 1,
    "KeyTwo": true,
    "KeyThree": {
        "Message": "Thanks for checking this out!"
    }
}

Ersetzen Sie den Inhalt der Datei Program.cs durch den folgenden C#-Code:

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!

Wenn Sie diese Anwendung ausführen, definiert Host.CreateApplicationBuilder das Verhalten, um die JSON-Konfiguration zu erkennen und über die IConfiguration-Instanz verfügbar zu machen. Aus der host-Instanz können Sie die IConfiguration-Instanz vom Dienstanbieter abrufen und dann Werte abrufen.

Tipp

Die Verwendung der rohen IConfiguration-Instanz auf diese Weise ist zwar praktisch, aber nicht sehr gut skalierbar. Wenn Anwendungen und damit die entsprechenden Konfigurationen komplexer werden, empfehlen wir, das Optionsmuster als Alternative zu verwenden.

Grundlegendes Beispiel für das Hosten und Verwenden der Indexer-API

Sehen Sie sich die Inhalte der appsettings.json-Datei aus dem vorherigen Beispiel an:

{
    "SupportedVersions": {
        "v1": "1.0.0",
        "v3": "3.0.7"
    },
    "IPAddressRange": [
        "46.36.198.123",
        "46.36.198.124",
        "46.36.198.125"
    ]
}

Ersetzen Sie den Inhalt der Datei Program.cs durch den folgenden C#-Code:

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

Auf die Werte wird mithilfe der Indexer-API zugegriffen, wobei sowohl jeder Schlüssel als auch der Wert eine Zeichenfolge ist. Die Konfiguration unterstützt Eigenschaften, Objekte, Arrays und Wörterbücher.

Konfigurationsanbieter

Die folgende Tabelle zeigt die für .NET Core-Apps verfügbaren Konfigurationsanbieter.

Anbieter Bereitstellung der Konfiguration über
Azure-App-Konfigurationsanbieter Azure App Configuration
Azure Key Vault-Konfigurationsanbieter Azure Key Vault
Befehlszeilen-Konfigurationsanbieter Befehlszeilenparameter
Benutzerdefinierter Konfigurationsanbieter Benutzerdefinierte Quelle
Umgebungsvariablen-Konfigurationsanbieter Umgebungsvariablen
Dateikonfigurationsanbieter JSON-, XML-und INI-Dateien
Schlüssel-pro-Datei-Konfigurationsanbieter Verzeichnisdateien
Speicherkonfigurationsanbieter In-Memory-Sammlungen
App-Geheimnisse (Secret Manager) Datei im Benutzerprofilverzeichnis

Tipp

Die Reihenfolge, in der Konfigurationsanbieter hinzugefügt werden, ist wichtig. Wenn mehrere Konfigurationsanbieter verwendet werden und ein und derselbe Schlüssel von mehr als einem Anbieter bereitgestellt wird, wird der zuletzt hinzugefügte Anbieter verwendet.

Weitere Informationen zu verschiedenen Konfigurationsanbietern finden Sie unter Konfigurationsanbieter in .NET.

Siehe auch