App.config(アプリケーション構成ファイル)を利用する

C#の実行形式のファイル(.NET Framework, .NET Core)にはアプリーション固有の設定を XML 形式で記述できるアプリケーション構成ファイルというものが添付できます。このファイルに設定を書いておくと起動時に自動的に読み込まれ以降、この設定を読み出すことができます。

確認環境

この記事は以下環境で確認しています。

  • VS2019
  • Windows10
  • .NET 5
  • .NET Core3.1
  • .NET Framework 4.8

System.Configurationのセットアップ

まず、使用を開始する前に .NET 5 などの一部の環境ではパッケージマネージャーからセットアップが必要です。.NET 5系でも Microsoft.WindowsDesktop.App.WindowsForms を使用している場合はセットアップ不要です。

Visual Studio の IDE から 「NuGet パッケージ マネージャー」を開いて「System.Configuration.ConfigurationManager」を導入するか、「パッケージマネージャー コンソール」にて以下を入力して追加のパッケージを導入します。

// URL:
// https://www.nuget.org/packages/System.Configuration.ConfigurationManager/

PM> Install-Package System.Configuration.ConfigurationManager -Version 5.0.0

値の定義方法

.NET Framework の場合、実行形式ファイルを作成するとプロジェクトにデフォルトで "App.config" というものがあるのでそのまま使用します。.NET Core の場合(もしくは存在しないプロジェクトの場合)、最初は存在しないので、プロジェクトのコンテキストメニューから以下の順でプロジェクトにファイルを追加します。

追加 > 新しい項目 > アプリケーション構成ファイル

追加したファイルを開くと以下のような初期状態になっています。

<!-- 追加したXML -->
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

ここに「キー」「値」形式で以下のように値を追加します。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="key1" value="abc" />
        <add key="key2" value="1" />
        <add key="key3" value="10.5" />
    </appSettings>
<
//configuration>

App,config には key-value の単純な組み合わせ以外にも独自の形式を定義する事ができます。しかしアクセス方法が独特で覚えるのがかなり面倒なので、そういった場青自分で外部ファイルを作成してデシリアライズしたほうが圧倒的に効率が良です。value に外部定義ファイルのパスを書いて2段階参照するのが定石かと思います。

また、設定値を App.config に書き込んで値を保持してると大抵の場合あとで大変なことになるため App.confg は読み取り専用で key-value の組み合わせ持つくらいの使い方に留めた方が良いでしょう。

もしどうしてもやりたい場合は使い方はこのサイトが詳しいです。ここでは解説しません。

定義した値の読み取り

基本的に、AppSettings セクションは以下のように記述して value を文字列として取得します。

string key1 = ConfigurationManager.AppSettings["key1"];

読み取り用のヘルパーを作成する

この、読み取った値は全て文字列として扱われてしまいますが、valuue が数値の場合、毎回変換するためのコードを書くのは大変なのでユーティリティを作成したいと思います。

使い方

先にユーティリティの使い方を紹介します。

// 定義値を文字列として取得する
int key1 = AppSetting.GetString("key1");

// 定義値をintとして取得する
int key2 = AppSetting.GetInt("key2");

// 定義値を TimeSpan 型として取得する、変換方法はラムダで指定する
TimeSpan span = AppSetting.GetTimeSpan("key4", value => TimeSpan.FromSeconds(value));

// 定義値を DateTime 型として取得する、変換方法はラムダで指定する
DateTime span = 
    AppSetting.GetDateTime("key5",
        str => DateTime.ParseExact(str, "yyyy/MM/dd HH:mm:ss.fff", null));

C#の基本型はすべてサポート + TimeSpan, DateTime も変換方法を指定すれば取得できます。ジェネリックを使用する方法もありますが一度オブジェクトに変換してキャストする関係で少し遅かったので基本型ごとに専用のメソッドを用意して値を取得します。

AppSettingクラス

実際の実装は以下の通りです。コピペでOK。

using System.Configuration;
using System.Globalization;
using System.Runtime.CompilerServices;

/// <summary>
/// App.config の appSetting セクションにアクセスするための汎用機能を提供します。
/// </summary>
public static class AppSetting
{
    #region 見本...
    //
    // 見本:
    // 以下のような App.config 内の appSetting ノードの中身に簡単にアクセスできるようにする
    //
    // <?xml version="1.0" encoding="utf-8" ?>
    // <configuration>
    //
    //     <appSettings>
    //         <add key="key" value="10"/>
    //     </appSettings>
    //
    // </configuration>
    //
    #endregion

    #region 補足...
    //
    // 補足:
    // App.config に任意の値を書き込むこともできるが大抵の場合ロクなことにならないので
    // この値は静的な定数としてアプリは値を読み取り専用で扱うのを推奨
    // 
    // 動的なパラメータこのファイルに記載せずに Settings や外部ファイルで扱う方がよい
    //
    #endregion

    /// <summary>
    /// appSetting セクションをリロードします。
    /// </summary>
    public static void Reload() => ConfigurationManager.RefreshSection("appSettings");

    /// <summary>
    /// appSetting セクション内の指定したキーに対応する値を取得します。
    /// </summary>
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static string GetString(string key) => ConfigurationManager.AppSettings[key];

    // 以下基本型として値を取得するメソッド

    public static bool GetBool(string key) => bool.Parse(GetString(key));
    public static byte GetByte(string key) => byte.Parse(GetString(key));
    public static sbyte GetSByte(string key) => sbyte.Parse(GetString(key));
    public static char GetChar(string key) => char.Parse(GetString(key));
    public static decimal GetDecimal(string key) => decimal.Parse(GetString(key));
    public static double GetDouble(string key) => double.Parse(GetString(key));
    public static float GetFloat(string key) => float.Parse(GetString(key));
    public static int GetInt(string key) => int.Parse(GetString(key));
    public static uint GetUInt(string key) => uint.Parse(GetString(key));
    public static long GetLong(string key) => long.Parse(GetString(key));
    public static ulong GetULong(string key) => ulong.Parse(GetString(key));
    public static short GetShort(string key) => short.Parse(GetString(key));
    public static ushort GetUShort(string key) => ushort.Parse(GetString(key));

    /// <summary>
    /// 設定値を指定したフォーマットで <see cref="DateTime"/> 型に変換して取得します。
    /// </summary>
    public static DateTime GetDateTime(string key, string format)
    {
        return DateTime.ParseExact(GetString(key), format, CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// 指定値を <see cref="TimeSpan"/> として取得します。変換は conv の処理を使用します。
    /// </summary>
    public static TimeSpan GetTimeSpan(string key, Func<double, TimeSpan> conv)
    {
        return conv(GetDouble(key));
    }
}

以上です。