しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Web.config から AppSettings クラスを作成する T4 を書いてみた

ASP.NET で開発していて毎回思うのが、設定を Web.config に持たせた時のコードからの扱いにくさです。例えば以下のように appSettings セクションに設定を追加します。

<appSettings>
  <add key="Foo" value="123" />
  <add key="Bar" value="456" />
  <add key="Baz" value="789" />
</appSettings>

実際にコードからこの設定を読み込もうとすると、以下のように冗長なコードを書く必要があります。

特にキーが文字列で指定しないといけないのが間違いの元ですし、非常にイケてないですよね。

// キーを文字列で指定しないといけない
var foo = ConfigurationManager.AppSettings["Foo"];

var bar = ConfigurationManager.AppSettings["Bar"];

var baz = ConfigurationManager.AppSettings["Baz"];

これだとインテリセンスも効かないですし、実際に使う時にめんどくさいですよね。

個人的には以下のようにクラスとして扱いたいわけです。これなら普通のクラスなのでインテリセンスが効くので、キー名の打ち間違いは起こらなくなります。

public static class AppSettings
{
    public static string Bar
    {
        get { return ConfigurationManager.AppSettings["Bar"]; }
    }

    public static string Baz
    {
        get { return ConfigurationManager.AppSettings["Baz"]; }
    }

    public static string Foo
    {
        get { return ConfigurationManager.AppSettings["Foo"]; }
    }

}

という訳で、良い感じに Web.config の appSettings セクションを読み込んでクラスにしてくれる T4 を書きました。

説明は省きますが、プロジェクト内の Web.config を読み込んでプロパティとして出力しているだけです。

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Configuration" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Linq" #>
<#@ output extension=".cs" #>
<#
var namespaceName = System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint").ToString();

var configFile = new ExeConfigurationFileMap();
configFile.ExeConfigFilename = Host.ResolvePath("Web.config");

var config = ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
var appSettings = config.AppSettings.Settings;
#>
using System.Configuration;

namespace <#= namespaceName #>
{
	public static class AppSettings
	{
<# foreach (var key in appSettings.AllKeys.OrderBy(p => p)) { #>
		public static string <#= key #>
		{
			get { return ConfigurationManager.AppSettings["<#= key #>"]; }
		}

<# } #>
	}
}

このテンプレートが実行されると、例にあげたような AppSettings クラスが生成されます。

f:id:shiba-yan:20130402212003p:plain

これで自動的にクラスとして吐き出してくれるので、便利に使えるようになりました。