# 機能設計書 32-Microsoft.Extensions.Configuration

## 概要

本ドキュメントは、Microsoft.Extensions.Configuration（構成管理）機能の設計内容を記述する。この機能は.NETアプリケーションにおける設定値の読み込み、管理、変更通知を統一的なAPIで提供する。

### 本機能の処理概要

Microsoft.Extensions.Configurationは、様々なソース（JSON、XML、環境変数、コマンドライン引数等）から設定値を読み込み、階層的なキー/バリュー形式で管理するフレームワークである。設定値の動的リロードと変更通知機能も提供する。

**業務上の目的・背景**：アプリケーション設定は、接続文字列、APIキー、機能フラグなど、環境によって異なる値を管理するために不可欠である。このライブラリは、複数の設定ソースを統合し、優先順位に基づいた設定値のオーバーライドを可能にする。開発環境、ステージング環境、本番環境で異なる設定を容易に管理でき、12-Factor Appの原則にも準拠している。

**機能の利用シーン**：アプリケーション起動時の設定読み込み、実行時の設定変更検知、環境別設定の切り替え、ユーザーシークレットの管理など、あらゆる設定管理シナリオで使用される。ASP.NET Core、Worker Service、コンソールアプリケーションで標準的に使用される。

**主要な処理内容**：
1. IConfigurationBuilderを通じた設定ソースの登録
2. ConfigurationRootの構築と設定値の読み込み
3. 階層的なキー（Section:Key形式）による設定値アクセス
4. IChangeTokenを通じた設定変更通知
5. 設定値のホットリロード
6. 設定セクションの取得とバインディング

**関連システム・外部連携**：Microsoft.Extensions.Configuration.Json（JSON設定）、Microsoft.Extensions.Configuration.EnvironmentVariables（環境変数）、Microsoft.Extensions.Configuration.CommandLine（コマンドライン）、Azure App Configuration、AWS Systems Manager Parameter Storeなど、様々な設定プロバイダーと連携する。

**権限による制御**：設定値自体にアクセス制御はないが、User Secretsや環境変数を使用することで、機密情報の安全な管理が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | Runtime Config Test（RuntimeConfig） | 補助機能 | ランタイム設定の読み込みテスト |

## 機能種別

データ連携 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | string | Yes | 設定キー（コロン区切りで階層表現） | null不可 |
| source | IConfigurationSource | Yes | 設定ソース | null不可 |
| path | string | No | ファイルパス（ファイルベースのソース） | 存在確認はオプション |
| optional | bool | No | ファイルが存在しない場合のエラー抑制 | - |
| reloadOnChange | bool | No | ファイル変更時の自動リロード | - |

### 入力データソース

- JSONファイル（appsettings.json等）
- XMLファイル
- INIファイル
- 環境変数
- コマンドライン引数
- メモリ内Dictionary
- Azure App Configuration
- User Secrets

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ConfigurationRoot | IConfigurationRoot | 構築された設定ルート |
| ConfigurationSection | IConfigurationSection | 設定セクション |
| Value | string | 設定値（文字列） |
| ChangeToken | IChangeToken | 変更通知トークン |

### 出力先

- アプリケーションの設定オブジェクト
- IOptions<T>パターンを通じたPOCOオブジェクト

## 処理フロー

### 処理シーケンス

```
1. 設定ビルダー初期化
   └─ ConfigurationBuilderインスタンス作成
2. ソース登録フェーズ
   └─ AddJsonFile、AddEnvironmentVariables等でソースを追加
3. 設定構築フェーズ
   └─ Build()で各ソースからプロバイダーを生成し、ConfigurationRootを作成
4. 設定読み込みフェーズ
   └─ 各プロバイダーのLoad()を実行
5. 設定アクセスフェーズ
   └─ インデクサやGetSection()で値を取得
6. 変更監視フェーズ（オプション）
   └─ GetReloadToken()で変更を監視し、Reload()で再読み込み
```

### フローチャート

```mermaid
flowchart TD
    A[ConfigurationBuilder作成] --> B[設定ソース追加]
    B --> C[Build呼び出し]
    C --> D[ConfigurationRoot作成]
    D --> E[各Provider.Load実行]
    E --> F{設定値要求}
    F -->|this[key]| G[プロバイダーを逆順検索]
    G --> H{値が見つかった?}
    H -->|Yes| I[値を返却]
    H -->|No| J[次のプロバイダー検索]
    J --> G
    F -->|GetSection| K[ConfigurationSection作成]
    K --> L[セクション返却]
    F -->|GetReloadToken| M[ChangeToken返却]
    M --> N{変更検知?}
    N -->|Yes| O[RaiseChanged]
    O --> P[Reload実行]
    P --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | 後勝ち優先 | 後から追加されたソースの値が優先される | 同一キーに複数の値がある場合 |
| BR-32-02 | キー区切り文字 | コロン(:)でセクションを階層化 | キー指定時 |
| BR-32-03 | 大文字小文字 | キーは大文字小文字を区別しない（通常） | プロバイダー依存 |
| BR-32-04 | 配列インデックス | 配列はKey:0、Key:1形式でアクセス | 配列設定時 |

### 計算ロジック

設定値検索順序：
1. プロバイダーリストを逆順（最後に追加されたものから）に検索
2. 最初に見つかった値を返却
3. 見つからない場合はnull

## データベース操作仕様

該当なし（メモリ内操作のみ、ただしプロバイダーによってはDB接続可能）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | FileNotFoundException | 必須ファイルが存在しない | optional:trueを指定するか、ファイルを配置 |
| - | FormatException | JSON/XML等の形式エラー | ファイル形式を修正 |
| - | InvalidOperationException | プロバイダーがない状態でSet | ソースを追加する |

### リトライ仕様

ファイル読み込みエラー時、reloadOnChangeが有効な場合は次回の変更検知時に再試行

## トランザクション仕様

該当なし

## パフォーマンス要件

- 設定値取得: O(n) - プロバイダー数に比例
- キャッシュなし（毎回プロバイダーを検索）
- ChangeTokenは変更検知のみ、ポーリングは行わない

## セキュリティ考慮事項

- 機密情報はUser SecretsまたはAzure Key Vaultを使用
- appsettings.jsonに機密情報を含めない
- 環境変数での機密情報管理を推奨

## 備考

- ConfigurationManagerは.NET 6で追加された簡易APIで、ソース追加と同時にプロバイダーが作成される
- IConfigurationとIConfigurationRootの違いに注意（Reloadはルートのみ）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

設定システムの基本的なインターフェースとデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IConfigurationBuilder.cs | `src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationBuilder.cs` | 設定ビルダーのインターフェース。Sources、Properties、Add、Buildメソッド |
| 1-2 | IConfigurationSource.cs | `src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationSource.cs` | 設定ソースのインターフェース。Buildメソッドでプロバイダーを生成 |
| 1-3 | IConfigurationProvider.cs | `src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/IConfigurationProvider.cs` | プロバイダーのインターフェース。TryGet、Set、Load、GetReloadToken |

**読解のコツ**: Source→Provider→Rootの階層を理解することが重要。Sourceは「設定の取得方法」、Providerは「設定の実データ」、Rootは「複数プロバイダーの統合ビュー」を提供する。

#### Step 2: エントリーポイントを理解する

ConfigurationBuilderからConfigurationRootの構築フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ConfigurationBuilder.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationBuilder.cs` | 設定ビルダーの実装。Sources リスト、Add、Buildメソッド |
| 2-2 | ConfigurationRoot.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs` | 設定ルートの実装。プロバイダーの統合、インデクサ、Reload |

**主要処理フロー**:
1. **ConfigurationBuilder.cs 32-38行目**: Add()でソースをリストに追加
2. **ConfigurationBuilder.cs 45-54行目**: Build()で各ソースからプロバイダーを生成し、ConfigurationRootを作成
3. **ConfigurationRoot.cs 27-38行目**: コンストラクタで各プロバイダーのLoad()を呼び出し、変更監視を設定
4. **ConfigurationRoot.cs 50-54行目**: インデクサでGetConfiguration/SetConfigurationを呼び出し
5. **ConfigurationRoot.cs 114-127行目**: GetConfigurationでプロバイダーを逆順検索

#### Step 3: プロバイダー実装を理解する

具体的なプロバイダーの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ConfigurationProvider.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs` | プロバイダーの基底クラス。Data Dictionary、TryGet、Set |
| 3-2 | MemoryConfigurationProvider.cs | `src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationProvider.cs` | メモリプロバイダーの実装例 |

**主要処理フロー**:
- **ConfigurationProvider.Data**: 設定値を保持するDictionary<string, string?>
- **TryGet()**: Dataから値を検索
- **Set()**: Dataに値を設定

#### Step 4: 変更通知を理解する

設定のホットリロードと変更通知の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ConfigurationReloadToken.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationReloadToken.cs` | 変更通知トークンの実装 |
| 4-2 | ConfigurationRoot.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs` | Reload、RaiseChanged、GetReloadTokenの実装 |

**主要処理フロー**:
- **ConfigurationRoot.cs 83-90行目**: Reload()で全プロバイダーのLoad()を再実行し、RaiseChangedを呼び出し
- **ConfigurationRoot.cs 92-96行目**: RaiseChanged()でChangeTokenを交換し、OnReload()を発火

### プログラム呼び出し階層図

```
ConfigurationBuilder.Build()
    │
    ├─ foreach (source in Sources)
    │      │
    │      └─ source.Build(this)
    │             │
    │             └─ IConfigurationProvider生成
    │
    └─ new ConfigurationRoot(providers)
           │
           ├─ foreach (provider in providers)
           │      │
           │      └─ provider.Load()
           │
           └─ ChangeToken.OnChange(provider.GetReloadToken, RaiseChanged)

ConfigurationRoot[key]
    │
    └─ GetConfiguration(providers, key)
           │
           └─ for (i = providers.Count - 1; i >= 0; i--)
                  │
                  └─ provider.TryGet(key, out value)
                         │
                         └─ value返却 or 次のプロバイダー
```

### データフロー図

```
[入力]                      [処理]                        [出力]

JSON/XML/ENV等 ───▶ IConfigurationSource ───▶ IConfigurationProvider
                                                      │
                                                      ▼
                                              provider.Load()
                                                      │
                                                      ▼
                           ConfigurationBuilder ─▶ ConfigurationRoot
                                                      │
                                                      ▼
this[key] ────────────────────────────────────▶ GetConfiguration()
                                                      │
                                                      ▼
                                              プロバイダー逆順検索
                                                      │
                                                      ▼
                                                 設定値(string)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ConfigurationBuilder.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationBuilder.cs` | ソース | 設定ビルダー実装 |
| ConfigurationRoot.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs` | ソース | 設定ルート実装 |
| ConfigurationProvider.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs` | ソース | プロバイダー基底クラス |
| ConfigurationSection.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationSection.cs` | ソース | 設定セクション実装 |
| ConfigurationReloadToken.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationReloadToken.cs` | ソース | 変更通知トークン |
| MemoryConfigurationProvider.cs | `src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationProvider.cs` | ソース | メモリプロバイダー |
| MemoryConfigurationSource.cs | `src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationSource.cs` | ソース | メモリソース |
| ChainedConfigurationProvider.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs` | ソース | チェインプロバイダー |
| ConfigurationManager.cs | `src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs` | ソース | 簡易設定マネージャー |
