2026年7月14日火曜日

WPF/C#で jsonを使ったAppSettingsの実装

1.パッケージ追加

microsoft.extensions.configuration.json

JSON形式の設定ファイル(appsettings.jsonなど)を読み込むための構成プロバイダー

パッケージのインストール

Visual Studioツール>NuGetマネージャー>パッケージ マネージャー コンソール以下を実行
PM> Install-Package Microsoft.Extensions.Configuration.Json

microsoft.extensions.hosting

依存関係の注入 (DI)構成管理 (Configuration)などを統合的に管理するためのライブラリ(汎用ホスト)

パッケージのインストール
Visual Studioのツール>NuGetマネージャー>ソリューションのNuGet パッケージの管理
Microsoft.Extensions.Hostingを検索>選択>プロジェクトにチェック>インストール

2.appsettiongs.json追加
 (ファイル名は他と干渉しなければ任意)


・ソリューションエクスプローラー>プロジェクト選択>追加>JavaScript JSON 構成ファイル>名前入力>追加

・追加されたappsettiongs.jsonを右クリック>プロパティー>ビルドアクション>ドロップダウンで[コンテンツ]に変更

・出力ディレクトリにコピー>ドロップダウンで[新しい場合はコピーする]に変更

この設定を行うことで、ビルド時に実行ファイル(.exe)と同じフォルダにJSONファイルが出力され、DIコンテナ(Microsoft.Extensions.Configuration など)から正しく読み込めるようになる。

2.Jsonに対応するクラス追加

appsettingsをいくつかに分割する前提で、全体を管理するクラスを作る。名前は任意。
分割した個々の要素(Section)に対応するクラスを作り、そのインスタンスをプロパティーとして設定する。

    public class RootSettings
    {
        // AppSettings をプロパティとして持つ
        public AppSettings AppSettings { get; set; } = new();
    }

appsettings.jsonの構成要素名と一致する名前でクラスを作る。
上記の例ではappsettings.jsonの中に”AppSettings"という要素がある。

3.App.xaml変更

StartupUriの設定を削除。

    StartupUri="MainWindow.xaml">

3.App.xaml.cs変更

コンストラクタでDIから受け取るServiceを登録

        public static IHost? AppHost { get; private set; }
        /// <summary>
        /// ホスト(Host)を構築し、設定ファイルとウインドウをDIコンテナに登録します。
        /// </summary>
        public App()
        {
            //他のアプリから起動された場合、カレントディレクトリが異なる場合があるため、exeのあるフォルダに変更する。
            System.Environment.CurrentDirectory = System.AppContext.BaseDirectory;

            AppHost = Host.CreateDefaultBuilder()
                .ConfigureServices((context, services) =>
                {
                    services.AddSingleton<StorageService>();
                    services.Configure<AppSettings>(context.Configuration);

                    var rootSettings = context.Configuration.Get<AppSettings>() ?? new AppSettings();
                    services.PostConfigure<AppSettings>(settings => { settings.PostConfigure(); });
                    // MainWindow や他の設定クラスに渡す AppSettings は、Options パターン(IOptions)を経由して取得したものをシングルトン登録する
                    services.AddSingleton<AppSettings>(provider =>
                    {
                        // ここで .Value を要求した時にAppSettingsが読み込まれ、PostConfigureが実行される
                        var options = provider.GetRequiredService<Microsoft.Extensions.Options.IOptions<AppSettings>>();
                        return options.Value;
                    });
                    // AppSettings には、rootSettings のAppSettingsインスタンスをそのまま渡す
                    services.AddSingleton<DirSettings>(provider =>
                    {
                        // DIコンテナから登録済みの rootSettings を取り出し、その中の AppSettings を返す
                        var appSettings = provider.GetRequiredService<AppSettings>();
                        return appSettings.DirSettings;
                    });
                    services.AddSingleton<FileSettings>(provider =>
                    {
                        // DIコンテナから登録済みの rootSettings を取り出し、その中の AppSettings を返す
                        var appSettings = provider.GetRequiredService<AppSettings>();
                        return appSettings.FileSettings;
                    });
                    // 画面をDIコンテナに登録
                    services.AddTransient<MainWindow>();
                    services.PostConfigure<AppSettings>(settings => { settings.PostConfigure(); });
                })
                .Build();
        }
        protected override async void OnStartup(StartupEventArgs e)
        {
            // ホストの起動
            await AppHost.StartAsync();

            // DIコンテナからMainWindowを取得(自動的にAppSettingsが注入される)
            var mainWindow = AppHost.Services.GetRequiredService<MainWindow>();
            mainWindow.Show();

            base.OnStartup(e);
        }

        protected override async void OnExit(ExitEventArgs e)
        {
            // アプリ終了時にホストをクリーンアップ
if (AppHost != null)
{
await AppHost.StopAsync();
}
AppHost.Dispose(); base.OnExit(e); }

4.MainWindow.xaml.cs変更

コンストラクタでDIから登録したServiceを受け取る。
MainWindowの設定に関わるものがある場合は
InitializeComponentの前に呼ぶ。

        public MainWindow(AppSettings settings)
        {
            this.DataContext = settings;
            InitializeComponent();
        }



0 件のコメント:

コメントを投稿