コンソールアプリでも App.congi に代わる新しい定義ファイルの形式である appsettings.json を使用する場合の設定と実装方法の紹介です。
ASP.NET Core および ASP.NET 5~6 であれば、IServiceCollection.Configure
したがって、定義ファイルにアクセスしやすいようヘルパークラスの実装例を紹介したいと思います。
確認環境
この記事は以下環境で確認しています。
- VisualStudio 2022
- .NET 6
- コンソールプロジェクトが作成済み
パッケージの導入
「NuGet パッケージの管理」の「参照」から探してもいいですが、微妙にわかりにくかったので「パッケージマネージャー コンソール」からインストールします。
ツール > NuGet パッケージ マネージャー > パッケージ マネージャー コンソール
NuGetのページ: https://www.nuget.org/packages/Microsoft.Extensions.Configuration.Json/
以下コマンドを入力します。
PM> Install-Package Microsoft.Extensions.Configuration.Json -Version 5.0.0
プロジェクトに間接的に必要なDLLが以下の通り追加されます。
// 結構大量に追加されます
Microsoft.Extensions.Configuration.Abstractions.dll
Microsoft.Extensions.Configuration.dll
Microsoft.Extensions.Configuration.FileExtensions.dll
Microsoft.Extensions.Configuration.Json.dll
Microsoft.Extensions.FileProviders.Abstractions.dll
Microsoft.Extensions.FileProviders.Physical.dll
Microsoft.Extensions.FileSystemGlobbing.dll
Microsoft.Extensions.Primitives.dll
定義ファイルの追加・編集
ソリューションエクスプローラー > 対象プロジェクトのコンテキストメニュー > 追加 > 新しい項目
「JSON ファイル」などの JSON 形式のファイルを選択し「appsetting.json」という名前で追加します。(実際は名前は何でも良いです)追加したらファイルのプロパティでビルドアクションを「コンテンツ」に変更し、出力先ディレクトリにコピーを「新しい場合上書きする」に変更します。
JSON ファイルの内容は以下の通りに編集します。
{ "MySettings": { "Key1": "Key1", "Key2": "Key2", "InnerSettings": { "Key3": "Key3", "Key4": "Key4" } } }
値の取得
以下のように書けばアクセスできるようになります。
using System.IO; using Microsoft.Extensions.Configuration; internal class AppMain { private static void Main(string[] args) { // 定義ファイルの読み書き用のオブジェクトを初期化する IConfigurationRoot configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, true).Build(); IConfigurationSection section = config.GetSection("MySettings"); string key1 = section["Key1"]; string key2 = section["Key2"]; // 取得できない場合null、例外は発生しない string strN = section["KeyXX"]; // 入れ子の場合「A:B」という風にコロンを挟む IConfigurationSection innerSection = config.GetSection("MySettings:InnerSettings"); string key3 = innerSection["Key3"]; string key4 = innerSection["Key4"]; } }
アクセス用のヘルパークラスの作成
上記のようなコードを毎回書くのも面倒なのでヘルパークラスを作成して手間を軽減したいと思います。
AppSettingJsonクラス
以前の XML 形式の「アプリケーション 構成ファイル」と似たような形でアクセスできるといいので以下のような「MySettings」セクションの下に key-value 形式で値が並んでいる定義ファイルを想定してヘルパークラスを作成したいと思います。
// appsetting.json { "MySettings": { "key1": "stringstring", "key2": 10, "key3": 123.5698 } }
実装は以下の通りです。
using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; using Microsoft.Extensions.Configuration; /// <summary> /// appsettings.json のセクションを簡単に操作できるようにするためのヘルパークラス /// </summary> public class AppSettingsSection { #region 見本... // // 見本: // 以下の通り記述されている appSettings.json 内のセクションへのアクセスを簡単にする // // appsetting.json // { // "Setting": { ★ここ // "key1": "stringstring", // "key2": 10, // "key3": 123.5698 // } // } // #endregion // 対象のセクション IConfigurationSection _section; // // Constructors // - - - - - - - - - - - - - - - - - - - - public AppSettingsSection(IConfigurationSection section) { _section = section ?? throw new ArgumentNullException(nameof(section)); } // // Static Methods // - - - - - - - - - - - - - - - - - - - - public static AppSettingsSection CreateInstance(string filePath, string sectionName) { if (File.Exists(filePath)) throw new FileNotFoundException($"File not found.", filePath); if (string.IsNullOrWhiteSpace(sectionName)) throw new ArgumentException($"Require {sectionName}", nameof(sectionName)); var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile(filePath, true, true) .Build(); return new AppSettingsSection(GetSection(config, sectionName)); } public static AppSettingsSection CreateInstance(IConfiguration config, string sectionName) { if (config == null) throw new ArgumentNullException(nameof(config)); if (string.IsNullOrWhiteSpace(sectionName)) throw new ArgumentException($"Requre {nameof(sectionName)}", nameof(sectionName)); return new AppSettingsSection(GetSection(config, sectionName)); } private static IConfigurationSection GetSection(IConfiguration config, string sectionName) { IConfigurationSection section = config.GetSection(sectionName) ?? throw new KeyNotFoundException($"{sectionName} section is not found."); return section; } // // Public Methods // - - - - - - - - - - - - - - - - - - - - /// <summary> /// appSetting セクション内の指定したキーに対応する値を取得します。 /// </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetString(string key) => GetValue(key); // 以下基本型として値を取得するメソッド public bool GetBool(string key) => Convert.ToBoolean(GetValue(key)); public byte GetByte(string key) => Convert.ToByte(GetValue(key)); public sbyte GetSByte(string key) => Convert.ToSByte(GetValue(key)); public char GetChar(string key) => Convert.ToChar(GetValue(key)); public decimal GetDecimal(string key) => Convert.ToDecimal(GetValue(key)); public double GetDouble(string key) => Convert.ToDouble(GetValue(key)); public float GetFloat(string key) => Convert.ToSingle(GetValue(key)); public int GetInt(string key) => Convert.ToInt32(GetValue(key)); public uint GetUInt(string key) => Convert.ToUInt32(GetValue(key)); public long GetLong(string key) => Convert.ToInt64(GetValue(key)); public ulong GetULong(string key) => Convert.ToUInt64(GetValue(key)); public short GetShort(string key) => Convert.ToInt16(GetValue(key)); public ushort GetUShort(string key) => Convert.ToUInt16(GetValue(key)); // 時刻で取得 public DateTime GetDateTime(string key, string format) => DateTime.ParseExact(GetString(key), format, CultureInfo.InvariantCulture); // 時間で取得 public TimeSpan GetTimeSpan(string key, Func<double, TimeSpan> conv) => conv(GetDouble(key)); // // Not-Public Methods // - - - - - - - - - - - - - - - - - - - - // 対象のセクションの値を取得する private string GetValue(string key) { return _section[key] ?? throw new KeyNotFoundException($"Key not found. key={key}"); } }