Delen via


Configuratie in .NET

Configuratie in .NET wordt uitgevoerd met behulp van een of meer configuratieproviders. Configuratieproviders lezen configuratiegegevens van sleutel-waardeparen met behulp van verschillende configuratiebronnen:

  • Instellingenbestanden, zoals appsettings.json
  • Omgevingsvariabelen
  • Azure Key Vault-
  • Azure App Configuration
  • Opdrachtregelargumenten
  • Aangepaste providers (geïnstalleerd of gemaakt)
  • Directorybestanden
  • .NET-objecten in het geheugen
  • Derde partijen

Notitie

Zie .NET Runtime-configuratie-instellingenvoor meer informatie over het configureren van de .NET-runtime zelf.

Concepten en abstracties

Gezien een of meer configuratiebronnen biedt het IConfiguration type een uniforme weergave van de configuratiegegevens. De configuratie is alleen-lezen en het configuratiepatroon is niet ontworpen om programmatisch schrijfbaar te zijn. De IConfiguration-interface is één weergave van alle configuratiebronnen, zoals wordt weergegeven in het volgende diagram:

De interface 'IConfiguration' is één weergave van alle configuratiebronnen.

Console-apps configureren

.NET-console-apps die zijn gemaakt met de nieuwe opdrachtsjabloon dotnet of Visual Studio maken standaard geen configuratiemogelijkheden beschikbaar. Als u configuratie wilt toevoegen in een nieuwe .NET-consoletoepassing, voegt u een pakketverwijzing toe aan 📦 Microsoft.Extensions.Configuration. Dit pakket vormt de basis voor configuratie in .NET-apps. Het biedt de ConfigurationBuilder en aanverwante typen.

using Microsoft.Extensions.Configuration;

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

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

// Outputs:
//   SomeValue

De voorgaande code:

  • Hiermee maakt u een nieuw ConfigurationBuilder-exemplaar.
  • Hiermee voegt u een verzameling sleutel-waardeparen toe aan de configuratiebouwer.
  • Roept de Build() methode aan om een IConfiguration-exemplaar te maken.
  • Hiermee schrijft u de waarde van de SomeKey-sleutel naar de console.

Hoewel in dit voorbeeld een in-memory configuratie wordt gebruikt, zijn er veel configuratieproviders beschikbaar, waarbij functionaliteit beschikbaar is voor bestandsgebaseerde omgevingsvariabelen, opdrachtregelargumenten en andere configuratiebronnen. Zie Configuratieproviders in .NETvoor meer informatie.

Alternatieve hostingbenadering

Uw apps doen doorgaans meer dan enkel het lezen van configuratie. Ze gebruiken waarschijnlijk afhankelijkheidsinjectie, logboekregistratie en andere services. De benadering .NET Generic Host wordt aanbevolen voor apps die gebruikmaken van deze services. U kunt in plaats daarvan een pakketverwijzing toevoegen aan 📦 Microsoft.Extensions.Hosting. Wijzig het Program.cs-bestand zodat het overeenkomt met de volgende code:

using Microsoft.Extensions.Hosting;

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

// Application code should start here.

await host.RunAsync();

De methode Host.CreateApplicationBuilder(String[]) biedt standaardconfiguratie voor de app in de volgende volgorde, van hoogste naar laagste prioriteit:

  1. Opdrachtregelargumenten met behulp van de opdrachtregelconfiguratieprovider.
  2. Omgevingsvariabelen met behulp van de configuratieprovider Omgevingsvariabelen .
  3. app-geheimen wanneer de app wordt uitgevoerd in de Development-omgeving.
  4. appsettings.Environment.json met behulp van de JSON-configuratieprovider. Bijvoorbeeld appsettings.Production.json en appsettings.Development.json.
  5. appsettings.json met de JSON-configuratieprovider.
  6. ChainedConfigurationProvider: voegt een bestaande IConfiguration toe als bron.

Als u een configuratieprovider toevoegt, worden eerdere configuratiewaarden overschreven. De opdrachtregelconfiguratieprovider bijvoorbeeld alle waarden van andere providers overschrijft omdat deze het laatst is toegevoegd. Als SomeKey is ingesteld in zowel appsettings.json als de omgeving, wordt de omgevingswaarde gebruikt omdat deze na appsettings.jsonis toegevoegd.

Bindend

Een van de belangrijkste voordelen van het gebruik van de .NET-configuratieabstracties is de mogelijkheid om configuratiewaarden te binden aan exemplaren van .NET-objecten. De JSON-configuratieprovider kan bijvoorbeeld worden gebruikt om appsettings.json bestanden toe te wijzen aan .NET-objecten en wordt gebruikt met afhankelijkheidsinjectie. Hierdoor kan het -optiepatroon, dat klassen gebruikt om sterk getypte toegang te bieden tot groepen van verwante instellingen. De standaardbinding is gebaseerd op weerspiegeling, maar er is een alternatieve brongenerator die u eenvoudig kunt inschakelen.

.NET-configuratie biedt verschillende abstracties. Houd rekening met de volgende interfaces:

  • IConfiguration: Vertegenwoordigt een set eigenschappen van de toepassingsconfiguratie voor sleutel/waarde.
  • IConfigurationRoot: vertegenwoordigt de wortel van een IConfiguration-hiërarchie.
  • IConfigurationSection: Vertegenwoordigt een sectie met toepassingsconfiguratiewaarden.

Deze abstracties zijn agnostisch voor hun onderliggende configuratieprovider (IConfigurationProvider). Met andere woorden, u kunt een IConfiguration exemplaar gebruiken voor toegang tot elke configuratiewaarde van meerdere providers.

De binder kan verschillende benaderingen gebruiken om configuratiewaarden te verwerken:

  • Directe deserialisatie (met behulp van ingebouwde conversieprogramma's) voor primitieve typen.
  • De TypeConverter voor een complex type als het type er een heeft.
  • Weerspiegeling voor een complex type met eigenschappen.

Notitie

De binder heeft enkele beperkingen:

  • Eigenschappen worden genegeerd als ze privé-setters hebben of als hun type niet kan worden geconverteerd.
  • Eigenschappen zonder bijbehorende configuratiesleutels worden genegeerd.

Bindende hiërarchieën

Configuratiewaarden kunnen hiërarchische gegevens bevatten. Hiërarchische objecten worden weergegeven met het gebruik van het : scheidingsteken in de configuratiesleutels. Als u toegang wilt krijgen tot een configuratiewaarde, gebruikt u het : teken om een hiërarchie te scheiden. Denk bijvoorbeeld aan de volgende configuratiewaarden:

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

De volgende tabel vertegenwoordigt voorbeeldsleutels en de bijbehorende waarden voor de voorgaande voorbeeld-JSON:

Sleutel Waarde
"Parent:FavoriteNumber" 7
"Parent:Child:Name" "Example"
"Parent:Child:GrandChild:Age" 3

Geavanceerde bindingsscenario's

De configuratiebinder heeft specifieke gedragingen en beperkingen bij het werken met bepaalde typen. Deze sectie bevat de volgende subsecties:

Binden aan woordenlijsten

Wanneer u de configuratie koppelt aan een Dictionary<TKey,TValue> locatie waar de waarde een onveranderbaar verzamelingstype (zoals matrices of lijsten) is, worden de verzamelingswaarden uitgebreid door herhaalde bindingen met dezelfde sleutel in plaats van ze te vervangen.

In het volgende voorbeeld ziet u dit gedrag:

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"])}");

Zie Bindingsconfiguratie voor woordenlijst breidt waarden uit voor meer informatie.

Woordenlijstsleutels met dubbele punten

Het dubbele punt (:) is gereserveerd als een hiërarchiescheidingsteken in configuratiesleutels. Dit betekent dat u geen dubbele punten in woordenlijstsleutels kunt gebruiken wanneer de bindingsconfiguratie wordt geconfigureerd. Als uw sleutels een dubbelpunt (zoals URL's of andere opgemaakte id's) bevatten, interpreteert het configuratiesysteem deze als hiërarchiepaden in plaats van letterlijke letters. Overweeg de volgende tijdelijke oplossingen:

  • Gebruik alternatieve scheidingstekens (zoals dubbele onderstrepingstekens) in uw configuratiesleutels __en transformeer deze indien nodig programmatisch.
  • Herserialiseer de configuratie handmatig als onbewerkte JSON met behulp van System.Text.Json of een vergelijkbare bibliotheek, die ondersteuning biedt voor dubbele punten in sleutels.
  • Maak een aangepaste mappinglaag die veilige toetsversies vertaalt naar de gewenste toetsen waarbij dubbele punten worden gebruikt.

Binden aan IReadOnly*-typen

De configuratiebinding biedt geen ondersteuning voor directe binding met IReadOnlyList<T>, IReadOnlyDictionary<TKey, TValue> of andere alleen-lezen verzamelingeninterfaces. Deze interfaces ontbreken de mechanismen die de binder nodig heeft om de verzamelingen te vullen.

Als u met alleen-lezenverzamelingen wilt werken, gebruikt u veranderlijke typen voor de eigenschappen die door de binder worden ingevuld en maakt u deze vervolgens beschikbaar als alleen-lezeninterfaces voor consumenten:

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}");
}

De implementatie van de configuratieklasse:

class SettingsWithReadOnly
{
    // Use mutable type for binding
    public List<string> Values { get; set; } = [];

    // Expose as read-only for consumers
    public IReadOnlyList<string> ValuesReadOnly => Values;
}

Met deze methode kan de binder de veranderbare List<string> vullen, terwijl het een onveranderbare interface aan consumenten presenteert via IReadOnlyList<string>.

Binden met geparameteriseerde constructors

Vanaf .NET 7 ondersteunt de configuratiebinding binding aan typen die één openbare geparameteriseerde constructor hebben. Hierdoor kunnen onveranderbare typen en records rechtstreeks vanuit de configuratie worden ingevuld:

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}");
}

De onveranderbare instellingenklasse:

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

Belangrijk

De binder ondersteunt alleen typen met één openbare geparameteriseerde constructor. Als een type meerdere openbare geparameteriseerde constructors heeft, kan de binder niet bepalen welke moet worden gebruikt en mislukt de binding. Gebruik één geparameteriseerde constructor of een parameterloze constructor met eigenschapssetters.

Basisvoorbeeld

Als u configuratiewaarden in de basisvorm wilt openen, gebruikt u het type rechtstreeks zonder hulp van de ConfigurationBuilder benadering.

Tip

Het type System.Configuration.ConfigurationBuilder verschilt van het type Microsoft.Extensions.Configuration.ConfigurationBuilder. Al deze inhoud is specifiek voor de Microsoft.Extensions.* NuGet-pakketten en -naamruimten.

Overweeg het volgende C#-project:

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

Het voorgaande projectbestand verwijst naar verschillende NuGet-configuratiepakketten:

Bekijk een voorbeeld van appsettings.json bestand:

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

Op basis van dit JSON-bestand ziet u nu een voorbeeld van een verbruikspatroon met behulp van de opbouwfunctie voor configuraties:

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

De voorgaande C#-code:

  • Instantieert een ConfigurationBuilder.
  • Voegt het "appsettings.json"-bestand toe dat moet worden herkend door de JSON-configuratieprovider.
  • Hiermee worden omgevingsvariabelen toegevoegd die worden herkend door de configuratieprovider voor omgevingsvariabelen.
  • Hiermee haalt u de benodigde sectie "Settings" en de bijbehorende Settings instantie op met behulp van de config-instantie.

Het Settings object heeft de volgende vorm:

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

Basisvoorbeeld met hosting

Voor toegang tot de IConfiguration-waarde kunt u opnieuw vertrouwen op het Microsoft.Extensions.Hosting NuGet-pakket. Maak een nieuwe consoletoepassing en plak de volgende inhoud van het projectbestand erin:

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

In het voorgaande projectbestand wordt gedefinieerd dat:

  • De toepassing is een uitvoerbaar bestand.
  • Een appsettings.json-bestand moet worden gekopieerd naar de uitvoermap wanneer het project wordt gecompileerd.
  • De Microsoft.Extensions.Hosting NuGet-pakketreferentie wordt toegevoegd.

Voeg het appsettings.json bestand toe aan de hoofdmap van het project met de volgende inhoud:

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

Vervang de inhoud van het Program.cs-bestand door de volgende 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!

Wanneer u deze toepassing uitvoert, definieert de Host.CreateApplicationBuilder het gedrag om de JSON-configuratie te detecteren en beschikbaar te maken via het IConfiguration exemplaar. Vanuit het host exemplaar kunt u de serviceprovider om het IConfiguration exemplaar vragen, en vervolgens om de waarden vragen.

Tip

Het gebruik van de onbewerkte IConfiguration instantie op deze manier, hoewel handig, schaalt niet erg goed. Wanneer toepassingen complexer worden en de bijbehorende configuraties complexer worden, raden we u aan om het patroon opties te gebruiken als alternatief.

Basisvoorbeeld met hosting en het gebruik van de indexeerfunctie-API

Houd rekening met dezelfde appsettings.json bestandsinhoud uit het vorige voorbeeld:

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

Vervang de inhoud van het Program.cs-bestand door de volgende 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

De waarden worden geopend met behulp van de indexeerfunctie-API waarbij elke sleutel een tekenreeks is en de waarde een tekenreeks is. Configuratie ondersteunt eigenschappen, objecten, matrices en woordenlijsten.

Configuratieproviders

In de volgende tabel ziet u de configuratieproviders die beschikbaar zijn voor .NET Core-apps.

Configuratieprovider Zorgt voor configuratie vanuit
Azure App Configuration Azure App Configuration (Configuratie van Azure-apps)
Azure Key Vault- Azure Key Vault
opdrachtregel Opdrachtregelparameters
Aangepast Aangepaste bron
Omgevingsvariabelen Omgevingsvariabelen
bestand JSON-, XML- en INI-bestanden
Sleutel per bestand Directorybestanden
Memory Verzamelingen in het geheugen
App-geheimen (geheimbeheer) Het bestand in de gebruikersprofielmap

Tip

De volgorde waarin configuratieproviders worden toegevoegd, is belangrijk. Wanneer meerdere configuratieproviders worden gebruikt en meer dan één provider dezelfde sleutel opgeeft, wordt de laatste toegevoegde sleutel gebruikt.

Zie Configuratieproviders in .NETvoor meer informatie over verschillende configuratieproviders.

Zie ook