【C#】App.config(アプリケーション構成)で設定を読み込む

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

確認環境

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

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

値の定義方法

.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>

もっと複雑なキー・値の組み合わせ以外の独自形式も定義できますが、定義方法の仕様を覚えるのも保守するのも非常に面倒なので自分で定義ファイルを作った方が良いのです。このファイルは凝った作りにしないようにしましょう。複雑な場合は自分で定義ファイルを作成しデシリアライズしたほうが運用性が高いです。その場合、定義ファイルのパスや名前をこの定義に記述して2段階参照するのが定石でしょう。

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

定義した値の読み取り

.NET F/Wの場合は、あらかじめプロジェクトの参照に「System.Configuration」を追加しておく。.NET Coreの場合パッケージマネージャーから「System.Configuration.ConfigurationManager」を追加する。

使い方は以下のように記述すると定義が文字列として取得できる。

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

読み取り用のヘルパー

読み取った値は全部文字列として取れてしまうので毎回数値変換のコードを書くことになるが大変面倒なのでヘルパーを以下の通り作成する。

使い方

先に使い方を紹介する。

// 定義値をintとして取得
int key2 = ConfigUtil.GetValue<int>("key2");

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

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

C#の基本型はすべてサポート + TimeSpan, DateTime も変換方法を指定すれば取得できる。

ConfigUtilクラス

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

// Copyright (C) 2020 Takap.
// This software is released under the MIT License.

using System;
using System.Collections.Generic;
using System.Configuration;


/// <summary>
/// アプリケーションコンフィグに関係する汎用操作を提供します。
/// </summary>
public static class ConfigUtil
{
    //
    // Fields
    // - - - - - - - - - - - - - - - - - - - -

    // 基本型の変換方法を定義するテーブル
    private static readonly Dictionary<Type, Func<string, object>> table = 
        new Dictionary<Type, Func<string, object>>()
    {
        { typeof(bool), str => bool.Parse(str) },
        { typeof(byte), str => byte.Parse(str) },
        { typeof(sbyte), str => sbyte.Parse(str) },
        { typeof(char), str => char.Parse(str) },
        { typeof(decimal), str => decimal.Parse(str) },
        { typeof(double), str => double.Parse(str) },
        { typeof(float), str => float.Parse(str) },
        { typeof(int), str => int.Parse(str) },
        { typeof(uint), str => uint.Parse(str) },
        { typeof(long), str => long.Parse(str) },
        { typeof(ulong), str => ulong.Parse(str) },
        { typeof(short), str => short.Parse(str) },
        { typeof(ushort), str => ushort.Parse(str) },
    };

    //
    // Public Methods
    // - - - - - - - - - - - - - - - - - - - -

    /// <summary>
    /// 指定したキー値を文字列として取得します。
    /// </summary>
    public static string GetValue(string key) => ConfigurationManager.AppSettings[key];

    /// <summary>
    /// 指定したキー値を {T} で指定した型として取得します。
    /// サポートされる方の種類は基本型のみで、それ以外は例外が発生します。
    /// </summary>
    public static T GetValue<T>(string key)
    {
        Type type = typeof(T);
        if (!table.ContainsKey(type))
        {
            throw new NotSupportedException(typeof(T).Name + " is notsuprted.");
        }
        return (T)table[type](GetValue(key));
    }

    /// <summary>
    /// 指定したキー値から <see cref="TimeSpan"/> を取得します。
    /// 読み取ったキー値は浮動小数点として解釈しラムダ式で変換方法を指定します。
    /// </summary>
    public static TimeSpan GetValue(string key, Func<double, TimeSpan> conv) => conv(GetValue<double>(key));

    /// <summary>
    /// 指定したキー値から <see cref="DateTime"/> を取得します。
    /// 読み取った定数文字列から日付への変換はラムダ式で指定します。
    /// </summary>
    public static DateTime GetValue(string key, Func<string, DateTime> conv) => conv(GetValue(key));
}

以上です。