.NET での構成

.NET での構成は、1 つまたは複数の構成プロバイダーを使用して実行されます。 構成プロバイダーは、以下のようなさまざまな構成ソースを使用して、キーと値のペアから構成データを読み取ります。

  • appsettings.json などの設定ファイル
  • 環境変数
  • Azure Key Vault
  • Azure App Configuration
  • コマンド ライン引数
  • インストール済みまたは作成済みのカスタム プロバイダー
  • ディレクトリ ファイル
  • メモリ内 .NET オブジェクト
  • サード パーティ プロバイダー

Note

.NET ランタイム自体の構成については、「.NET ランタイム構成設定」を参照してください。

概念と抽象化

1 つ以上の構成ソースがある場合、IConfiguration 型によって構成データの統合ビューが提供されます。 構成は読み取り専用であり、構成パターンはプログラムで書き込むことができるように設計されていません。 IConfiguration インターフェイスは、次の図に示すように、すべての構成ソースの単一の表現です。

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

コンソール アプリの構成

既定で dotnet new コマンド テンプレートまたは 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 Generic Host アプローチをお勧めします。 代わりに、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[]) メソッドにより、優先度の高い方から低い方へ、次の順序でアプリの既定の構成が提供されます。

  1. コマンドライン構成プロバイダーを使用するコマンドライン引数。
  2. 環境変数構成プロバイダーを使用する環境変数。
  3. Development 環境でアプリが実行される際の App シークレット
  4. JSON 構成プロバイダーを使用する appsettings.json
  5. JSON 構成プロバイダーを使用する appsettings.Environmentjson。 たとえば、appsettings.Production.json および appsettings.Development.json
  6. ChainedConfigurationProvider: 既存の IConfiguration をソースとして追加します。

構成プロバイダーを追加すると、以前の構成値がオーバーライドされます。 たとえば、コマンドライン構成プロバイダーは最後に追加されるため、他のプロバイダーのすべての値がオーバーライドされます。 SomeKeyappsettings.json と環境の両方で設定されている場合、環境の値は appsettings.json の後に追加されたため、環境の値が使用されます。

バインド

.NET 構成の抽象化を使用する主な利点の 1 つは、構成値を .NET オブジェクトのインスタンスにバインドできることです。 たとえば、JSON 構成プロバイダーは、appsettings.json ファイルを .NET オブジェクトにマップするのに使用でき、依存関係の挿入で使用されます。 これによりオプション パターンが有効になります。これは、クラスを使用して、関連する設定のグループに厳密に型指定されたアクセスを提供します。 .NET 構成では、さまざまな抽象化が提供されます。 次のインターフェイスについて考えてみましょう。

  • IConfiguration: キー/値のアプリケーション構成プロパティのセットを表します。
  • IConfigurationRoot: IConfiguration 階層のルートを表します。
  • IConfigurationSection: アプリケーション構成値のセクションを表します。

これらの抽象化は、基になる構成プロバイダー (IConfigurationProvider) に依存します。 つまり、IConfiguration インスタンスを使用して、複数のプロバイダーから任意の構成値にアクセスできます。

バインダーでは、構成値を処理するためにさまざまな方法を使用できます。

  • プリミティブ型を直接逆シリアル化する (組み込みコンバーターを使用)。
  • 複合型の TypeConverter (型に備わっている場合)。
  • プロパティを持つ複合型のリフレクション。

Note

バインダーにはいくつかの制限があります。

  • プライベート セッターがある場合、またはその型を変換できない場合、プロパティは無視されます。
  • 対応する構成キーのないプロパティは無視されます。

バインド階層

構成値には階層データを含めることができます。 階層オブジェクトは、構成キーで : 区切り記号を使って表されます。 構成値にアクセスするには、: 文字を使って階層を区切ります。 たとえば、次のような構成値について考えてみます。

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

次の表は、上記の JSON 例に対するキーの例とその対応する値を表しています。

Key Value
"Parent:FavoriteNumber" 7
"Parent:Child:Name" "Example"
"Parent:Child:GrandChild:Age" 3

基本的な例

汎用ホスト アプローチのサポートなしに、基本形式で構成値にアクセスするには、ConfigurationBuilder 型を直接使用します。

ヒント

System.Configuration.ConfigurationBuilder 型は Microsoft.Extensions.Configuration.ConfigurationBuilder 型と異なります。 このコンテンツはすべて、Microsoft.Extensions.* NuGet パッケージと名前空間に固有です。

次の C# プロジェクトについて考えてみましょう。

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

前のプロジェクト ファイルでは、次の複数の構成 NuGet パッケージが参照されています。

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 をインスタンス化します。
  • JSON 構成プロバイダーによって認識される "appsettings.json" ファイルを追加します。
  • 環境変数構成プロバイダーによって認識される環境変数を追加します。
  • config インスタンスを使用して、必要な "Settings" セクションと対応する Settings インスタンスを取得します。

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

前のプロジェクト ファイルでは、次のものを定義します。

  • アプリケーションが実行可能ファイルである。
  • プロジェクトのコンパイル時に、appsettings.json ファイルを出力ディレクトリにコピーする。
  • Microsoft.Extensions.Hosting NuGet パッケージ参照が追加されている。

次の内容を含む 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 App Configuration プロバイダー Azure App Configuration
Azure Key Vault 構成プロバイダー Azure Key Vault
コマンド ライン構成プロバイダー コマンド ライン パラメーター
カスタム構成プロバイダー カスタム ソース
環境変数構成プロバイダー 環境変数
ファイル構成プロバイダー JSON、XML、および INI ファイル
ファイルごとのキーの構成プロバイダー ディレクトリ ファイル
メモリ構成プロバイダー メモリ内コレクション
アプリのシークレット (Secret Manager) ユーザー プロファイル ディレクトリ内のファイル

ヒント

構成プロバイダーを追加する順序は重要です。 複数の構成プロバイダーが使用され、複数で同じキーが指定されている場合は、最後に追加されたものが使用されます。

さまざまな構成プロバイダーの詳細については、「.NET の構成プロバイダー」を参照してください。

関連項目