アプリケーション構成ファイル「App.config」とは、アプリケーション固有の設定が記述されたXML形式のファイルです。このファイルは、アプリケーションの初期設定ファイル、以前のiniファイルとして利用します。

アプリケーション構成ファイルの作成

Visual Studioのソリューションエクスプローラでプロジェクトを右クリックして、ポップアップメニューを表示させます。メニューの「追加」-「新しい項目の追加」を選び、「新しい項目の追加」ダイアログを表示させます。ここで「アプリケーション構成ファイル」を選んで「追加」ボタンをクリックすると、「アプリケーション構成ファイル」が作成されます。

アプケーション構成ファイルの選択

設定データの読み込み

設定例として、次のように要素を追加し、さらにその中に要素を必要なだけ追加していきます。key属性が設定名で、value属性が設定の値になります。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="Application Name" value="MyApplication" />
        <add key="Application Version" value="1.0.0.0" />
        <add key="Comment" value="Hoge Hoge" />
    </appSettings>
</configuration>

*注意

「<configuration>」だと「App.configの’configration要素が宣言されていません」の警告が出ます。「<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">」と修正します。

app.configには、標準サポートされている単純なkey=value形式の設定として「appSettings」セクションを使うことができます。上記で作成したapp.configの内容をすべて表示するプログラムを次に示します。なお、ConfigurationManagerでエラーになっている場合、必要なdllが参照されていないケースがほとんどです。アセンブリ: System.Configuration (system.configuration.dll 内)となっていますが、これが「参照設定」にあるかを確認してください。

using System.Configuration;

//指定したキーの値を取得
//見つからないときはnullを返す
Console.WriteLine(System.Configuration.ConfigurationManager.AppSettings["Comment"]);

//すべてのキーとその値を取得
foreach (string key in System.Configuration.ConfigurationManager.AppSettings.AllKeys)
{
    Console.WriteLine("{0} : {1}",
        key, System.Configuration.ConfigurationManager.AppSettings[key]);
}

appSettingsのグループ分割

app.configで標準サポートされている「appSettings」セクションをグループ分けしたりファイルとして独立させる場合、独自のセクションを設けることで、各セクションごとに別ファイルに分割できます。

独自のセクションの定義はアプリケーション構成ファイルの「configSections/section」タグで設定します。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!-- configSectionsの定義は、app.configの先頭に書く必要がある -->
  <configSections>
    <!-- 独自に指定したセクション、
         NameValueFileSectionHandlerを指定しているので、扱い方はappSettingsと同じ -->
    <section name="appSettings2"
             type="System.Configuration.NameValueFileSectionHandler"
             restartOnExternalChanges="false"/>
  </configSections>

  <!-- DotNET標準のappSettingsセクション、キーと値のペアのリスト -->
  <appSettings>
    <add key="key1" value="value1"/>
    <add key="key2" value="日本語もOK"/>
  </appSettings>

  <!-- 独自に指定したセクション、扱い方はappSettingsと同じ.
       configSource属性によって、どのセクションであっても外部ファイルに分割することできる.
       (実行ファイルのフォルダへのコピーを忘れずに!)
       appSettingsが大きくなった場合には、この方法でセクションとファイルを分割することができる -->
  <appSettings2 configSource="appSettings2.xml"/>
</configuration>

上記の例では新しいセクション「appSettings2」を定義し、クラスを「NameValueFileSectionHandler」とします。これは、標準のappSettingsと同じクラスであるため、アプリケーション側では同じような方法で設定値にアクセスできます。また、セクションの属性として「configSource=”appSettings2.xml”」と指定しているため、そのセクションは外部ファイルから取り込まれます。

独自に設定した「appSettings2」へのアクセスは、次のになります。

var appSettings2 = (NameValueCollection)
  ConfigurationManager.GetSection("appSettings2");
foreach (string key in appSettings2)
{
   string value = appSettings2[key];
   System.Diagnostics.Trace.WriteLine("appSettings2: " + key + "=" + value);
}

この設定ファイル「appSettings2.xml」は、.configからの相対パスでアクセスされる為、コンパイル時にexeファイルと同じ位置にコピーされるように設定します。
構成ファイルのプロパティ変更

アプリケーション固有のデータ構造を持つ独自のセクションの定義方法

app.configは、アプリケーション固有のデータ構造が記述できます。「key = value」の形式では、うまく表現できないデータ構造の設定を簡潔に記述するには、独自のセクションを使います。独自のセクションを定義するには、まずSystem.Configuration.ConfigurationSectionを継承したクラスを作成します。このクラスに対して、ConfigurationProperty属性をもつプロパティを定義することで、設定の属性や要素を定義します。

このプロパティの型によって、設定ファイル上の意味が次のように異なります。

  • プロパティがint, stringなどの単一型を示す場合は、「属性」となります。
  • プロパティがConfigurationElement派生クラスである場合は、「要素」となります。
  • プロパティがConfigurationElementCollection派生クラスである場合は、「要素のコレクション」となります。

ここでは「serverConfig」という独自のセクションを「FooNetConfigHandler」というクラスで設定しています。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!-- configSectionsの定義は、app.configの先頭に書く必要がある -->
  <configSections>
    <!-- 独自に指定したカスタムセクション、
         独自のFooNetConfigHandlerクラスで設定内容にアクセスする -->
    <section name="serverConfig"
             type="AppConfigTest.FooNetConfigHandler, AppConfigTest"
             restartOnExternalChanges="false"/>
  </configSections>

  <!-- 独自のフォーマットで定義したカスタムセクション -->
  <serverConfig name="serverConf1">
    <defaultServer name="defaultServer1" address="1.2.3.4" port="80"/>
    <servers>
      <add name="host1" address="1.2.3.4" port="81"/>
      <add name="host2" address="1.2.3.5" port="82"/>
      <add name="host3" address="1.2.3.6" port="83"/>
    </servers>
  </serverConfig>
</configuration>

このクラスと、それが内包する要素の定義は以下のとおり。

    public class FooNetConfigHandler : ConfigurationSection
    {
        /// <summary>
        /// name属性
        /// </summary>
        [ConfigurationProperty("name", IsRequired = false)]
        public string Name
        {
            get
            {
                return (string)this["name"];
            }
            set
            {
                this["name"] = value;
            }
        }

        /// <summary>
        /// defaultServer要素
        /// </summary>
        [ConfigurationProperty("defaultServer", IsRequired = true)]
        public FooNetConfigItem DefaultServer
        {
            get
            {
                return (FooNetConfigItem)this["defaultServer"];
            }
        }

このようにして設定された独自のセクションにアクセスするには、以下のようにセクション名を指定してキャストするだけです。複数の属性からなる定型的なデータが0個以上の不特定数あるような場合、key=valueで表現するには末尾に連番をつけるなど小賢しい技が必要となりますが、独自のセクションを作れば、アプリケーション的にもデータ構造的にアクセスしやすく、設定ファイルも見やすくなるというメリットがあります。

  // 独自に定義したセクション
    var serverConfig = (FooNetConfigHandler)
        ConfigurationManager.GetSection("serverConfig");
    System.Diagnostics.Trace.WriteLine("serverConfig.Name=" + serverConfig.Name);
    System.Diagnostics.Trace.WriteLine("serverConfig.defaultServer=" + serverConfig.DefaultServer);