SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

状態遷移表からStateパターンを自動生成する

T4 templateで楽にコードを書こう


  • X ポスト
  • このエントリーをはてなブックマークに追加

 状態遷移表に基づいてコードに落とすのは単調な作業です。状態の数だけclassを起こし、それぞれのclassに事象の数だけメソッドを定義するので、どのclassもまったく同じ構造です。お定まりのパターンを何度も淡々を繰り返すのは退屈ですが、計算機はこのテの作業が大好きです。今回のお題は「状態遷移表からC#コードを自動生成させてみたよ」です。

  • X ポスト
  • このエントリーをはてなブックマークに追加

 前回のStateパターンのお話、おかげさまでかなり好評だったようです。流行のトレンドを追いかけるのはドキドキがいっぱいでモチベーションを維持する良い材料ではありますが、トレンドを楽しむにも「やりたい事をカタチにする」ために設計と実装の腕を磨いておかにゃなりませんですね。Stateパターンを適用すれば、状態(State)と事象(Event)および状態遷移表に基づいて見通しが良く変更に強い(かつ柔軟な)コードに落とすことができます。

 状態遷移表に基づいてコードに落とすのは単調な作業です。状態の数だけclassを起こし、それぞれのclassに事象の数だけメソッドを定義するので、どのclassもまったく同じ構造です。お定まりのパターンを何度も淡々を繰り返すのは退屈ですが、計算機はこのテの作業が大好きです。文句も言わず嬉々としてやってくれます。今回のお題は「状態遷移表からC#コードを自動生成させてみたよ」です。

Hello, world

 ソースコードって、つまりはテキストですよね。ですからテキストで与えられたひな型と変換規則(ここでは状態遷移表)、与えられた変換規則をひな型に適用してテキストを出力する適当なツールがあればいい。嬉しいことに、Visual Studio 2005以降ではTextTransformという名のテキスト→テキスト変換ツール「T4(Text To Text Transform)」が組み入れられています。実行形式TextTransform.exeは、Visual Studio 2010をデフォルト・インストールしていれば「C:\Program Files\Common Files\Microsoft Shared\TextTemplating\10.0」にあり(64bit Windowsなら「C:\Program Files (x86)\...」)、ここにPathを通せばコマンドラインからも利用できます。

T4 templateの使い方

 まず、C#コンソールアプリケーションプロジェクト「T4demo」を用意します。つぎに[新しい項目の追加]で「テキストテンプレート」を選択します。ファイル名はHello.ttとしておきましょうか。

「テキストテンプレート」を選択
「テキストテンプレート」を選択
ファイル名をHello.ttに設定
ファイル名をHello.ttに設定

 デフォルトでは<#@ output extension=".txt" #>によって生成されるファイルの拡張子が.txtになっているので.csに変更し、やおらC#コードを書きます。

Hello.tt
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
using System;

class Hello {
  static public void say(string name) {
    Console.WriteLine("Hello, {0}",name);
  }
}

 ここでいったんsaveすると、Hello.ttから生成されたコード「Hello.cs」がプロジェクトに追加されます。

 Program.csにHello.say()を呼び出すよう、少しだけ修正します。

Program.cs
namespace T4demo {
  class Program {
    static void Main() {
      Hello.say("T4");
    }
  }
}

 これで完了。buildするとHello.ttから生成されたHello.csとProgram.csがコンパイルされT4demo.exeが作られます。実行してみてください。"Hello, T4"が出力されましたか?

T4demo.exe実行画面
T4demo.exe実行画面

<# コードの埋め込み #>

 次に、"Hello, T4"を3回出力します。Hello.ttでConsole.WriteLine(...)を3つ書き連ねてもいいけども、それじゃあまりにつまらない。for-loopで繰り返しましょう。

Hello.tt
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
using System;

class Hello {
  static public void say(string name) {
<# for ( int i = 0; i < 3; ++i ) { #>
    Console.WriteLine("Hello, {0}",name);
<# } #>
  }
}

 このテンプレートからは、以下のコードが生成されます。

Hello.cs
using System;

class Hello {
  static public void say(string name) {
    Console.WriteLine("Hello, {0}",name);
    Console.WriteLine("Hello, {0}",name);
    Console.WriteLine("Hello, {0}",name);
  }
}

 要するに<# と #>で囲まれた部分がC#の文として埋め込まれるわけです。

<#= 式の展開 #>

 <#= と #>で囲まれた式は、その評価値が出力テキストに展開されます。

Hello.tt
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
using System;

class Hello {
  static public void say(string name) {
    Console.WriteLine("Hello, {0}",name);
<# foreach ( string fruit in new string[] { "apple", "banana", "cherry" }) { #>
    Console.WriteLine("I like <#= fruit.ToUpper() #>");
<# } #>
  }
}

 このテンプレートからは、以下のコードが生成されます。

Hello.cs
using System;

class Hello {
  static public void say(string name) {
    Console.WriteLine("Hello, {0}",name);
    Console.WriteLine("I like APPLE");
    Console.WriteLine("I like BANANA");
    Console.WriteLine("I like CHERRY");
  }
}

次のページ
<#+ メンバ定義 #>

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5783 2011/05/27 19:12

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング