mcpField
C
configuration

configuration

github.com/codewithmukesh開発7913.0k 回インストール12 週間前に更新
リポジトリ

configuration について

強く型付けされたオプション、検証、階層化されたソースでアプリ設定を管理する .NET 開発向けスキルです。シークレットの扱いと名前付きオプションも解説します。

主な機能

  1. 01強く型付けされたオプションのバインド
  2. 02起動時の設定検証
  3. 03階層化された設定ソース
  4. 04シークレット保管の指針
  5. 05名前付きオプション

活用シーン

  1. 01設定を検証済みクラスにバインド
  2. 02起動時に設定エラーを検出
  3. 03シークレットをソースコードから分離

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/codewithmukesh/dotnet-claude-kit --skill configuration

インストール後、Claude Code で/configurationを入力して読み込まれたか確認します。

詳細

構成

基本原則

  1. 常に Options パターンを使用する — サービス内で IConfiguration を直接読み取らないでください。構成セクションを、検証機能を備えた厳密な型のクラスにバインドします。
  2. 起動時に検証する — ValidateDataAnnotations() と ValidateOnStart() を使用して、最初のリクエストを受け付ける前に構成の誤りを検出します。
  3. シークレットをソースに含めない — 開発環境ではユーザーシークレットを、本番環境では Azure Key Vault または環境変数を使用します。シークレットを git にコミットしないでください。
  4. 構成の優先順位 — appsettings.json → appsettings.{Environment}.json → 環境変数 → ユーザーシークレット。後のソースが前のソースを上書きします。

パターン

Options パターン
// Options class with validation attributes
public class DatabaseOptions
{
    public const string SectionName = "Database";

    [Required]
    public required string ConnectionString { get; init; }

    [Range(1, 100)]
    public int MaxRetryCount { get; init; } = 3;

    [Range(1, 60)]
    public int CommandTimeoutSeconds { get; init; } = 30;
}

// Registration with validation
builder.Services.AddOptions<DatabaseOptions>()
    .BindConfiguration(DatabaseOptions.SectionName)
    .ValidateDataAnnotations()
    .ValidateOnStart(); // Fails at startup if configuration is invalid
// appsettings.json
{
  "Database": {
    "ConnectionString": "",
    "MaxRetryCount": 3,
    "CommandTimeoutSeconds": 30
  }
}
Options の注入
// IOptions<T> — singleton, read once at startup, doesn't change
public class OrderService(IOptions<DatabaseOptions> options)
{
    private readonly DatabaseOptions _db = options.Value;
}

// IOptionsSnapshot<T> — scoped, re-reads per request (for reloadable config)
public class OrderService(IOptionsSnapshot<DatabaseOptions> options)
{
    private readonly DatabaseOptions _db = options.Value;
}

// IOptionsMonitor<T> — singleton, actively watches for changes
public class BackgroundWorker(IOptionsMonitor<WorkerOptions> options)
{
    public void DoWork()
    {
        var current = options.CurrentValue; // Always latest
    }
}
カスタム検証(複雑なルール)
builder.Services.AddOptions<JwtOptions>()
    .BindConfiguration("Jwt")
    .Validate(options =>
    {
        if (string.IsNullOrEmpty(options.Key) || options.Key.Length < 32)
            return false;
        if (options.ExpirationMinutes <= 0)
            return false;
        return true;
    }, "JWT key must be at least 32 characters and expiration must be positive")
    .ValidateOnStart();
Azure Key Vault(本番環境)
// Program.cs — add Key Vault as a configuration source
if (builder.Environment.IsProduction())
{
    var keyVaultUri = new Uri(builder.Configuration["KeyVault:Uri"]!);
    builder.Configuration.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());
}
複数の環境向けの構成
// Named options — different config per named instance
builder.Services.AddOptions<SmtpOptions>("internal")
    .BindConfiguration("Smtp:Internal");
builder.Services.AddOptions<SmtpOptions>("customer")
    .BindConfiguration("Smtp:Customer");

// Usage
public class EmailService(IOptionsSnapshot<SmtpOptions> options)
{
    public async Task SendInternalEmail(string to, string body)
    {
        var smtp = options.Get("internal");
        // ...
    }
}

アンチパターン

IConfiguration を直接読み取らない
// BAD — stringly-typed, no validation, hard to test
public class OrderService(IConfiguration config)
{
    public void Process()
    {
        var timeout = int.Parse(config["Database:CommandTimeout"]!);
    }
}

// GOOD — strongly-typed options
public class OrderService(IOptions<DatabaseOptions> options)
{
    public void Process()
    {
        var timeout = options.Value.CommandTimeoutSeconds;
    }
}
シークレットを appsettings.json に記述しない
// BAD — committed to source control
{
  "Jwt": { "Key": "super-secret-key" },
  "Database": { "ConnectionString": "Server=prod;Password=secret" }
}

// GOOD — appsettings.json has defaults/structure only
{
  "Jwt": { "Key": "", "Issuer": "myapp", "Audience": "myapp" },
  "Database": { "ConnectionString": "" }
}
// Secrets provided via user-secrets (dev) or env vars / Key Vault (prod)
起動時の検証を省略しない
// BAD — misconfiguration discovered at runtime
builder.Services.Configure<JwtOptions>(builder.Configuration.GetSection("Jwt"));

// GOOD — fail fast at startup
builder.Services.AddOptions<JwtOptions>()
    .BindConfiguration("Jwt")
    .ValidateDataAnnotations()
    .ValidateOnStart();

判断ガイド

シナリオ推奨事項
クラスへの構成のバインドBindConfiguration を使用した Options パターン
シンプルで変更されない構成IOptions<T>
リクエストごとに変わる構成IOptionsSnapshot<T>
構成を監視するバックグラウンドサービスIOptionsMonitor<T>
開発環境のシークレットdotnet user-secrets
本番環境のシークレットAzure Key Vault または環境変数
構成の検証ValidateDataAnnotations() + ValidateOnStart()
同じ型の複数の構成IOptionsSnapshot<T>.Get(name) を使用した名前付き Options

コメント