Visual Studio 2017 を使用することをお勧めします

T4 テキスト テンプレートを使用したデザイン時コード生成

 

Visual Studio 2017 RC の最新のドキュメントの詳細については、Visual Studio 2017 RC ドキュメントをご参照ください。

デザイン時 T4 テキスト テンプレートを使用して、Visual Studio プロジェクトのプログラム コードや他のファイルを生成できます。 テンプレートを作成するときは、モデルのデータに応じて生成されるコードが変わるようにするのが一般的です。 モデルとは、アプリケーションの要件に関する重要な情報が含まれたファイルまたはデータベースのことです。

たとえば、ワークフローをテーブルまたは図として定義したモデルがあるとします。 このモデルから、ワークフローを実行するソフトウェアを生成できます。 ユーザーの要件が変わったときに、新しいワークフローについてユーザーと共に検討しやすくなります。 ワークフローからコードを再生成すると、コードを手動で更新するよりも信頼性が高まります。

System_CAPS_ICON_note.jpg メモ

モデルは、アプリケーションの特定の側面を記述したデータ ソースです。 モデルはどのような形式でもかまいません。あらゆる種類のファイルまたはデータベースを使用できます。 UML モデルやドメイン固有言語モデルなどの特定の形式である必要はありません。 標準的なモデルの形式は、テーブルまたは XML ファイルです。

コード生成は決して新しい概念ではありません。 .resx ソリューションにある Visual Studio ファイルでリソースを定義すると、一連のクラスおよびメソッドが自動的に生成されます。 リソースの編集は、クラスやメソッドを直接編集するよりも、リソース ファイルで行った方がはるかに簡単で確実です。 同様に、テキスト テンプレートを使用すると、独自に設計したソースからコードを生成することができます。

テキスト テンプレートには、生成するテキストと、テキストの可変部分を生成するプログラム コードの組み合わせが含まれます。 プログラム コードにより、生成されるテキストの一部を繰り返したり、条件に従って省略したりできるようになります。 生成されるテキスト自体を、アプリケーションの一部となるプログラム コードにすることもできます。

Visual Studio でデザイン時 T4 テンプレートを作成するには

  1. Visual Studio プロジェクトを作成するか、既存のプロジェクトを開きます。

    たとえば、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。

  2. テキスト テンプレート ファイルをプロジェクトに追加し、ファイル名の拡張子を .tt にします。

    そのために、ソリューション エクスプローラーで、プロジェクトのショートカット メニューを開き、[追加][新しい項目] の順にクリックします。 [新しい項目の追加] ダイアログ ボックスで、中央のペインの [テキスト テンプレート] を選択します。

    ファイルの [カスタム ツール] プロパティが TextTemplatingFileGenerator となっていることに注目してください。

  3. ファイルを開きます。 既に次のディレクティブが指定されています。

    <#@ template hostspecific="false" language="C#" #>  
    <#@ output extension=".txt" #>  
    
    

    Visual Basic プロジェクトにテンプレートを追加した場合、言語属性は "VB" になります。

  4. ファイルの最後にテキストを追加します。 次に例を示します。

    Hello, world!  
    
    
  5. ファイルを保存します。

    テンプレートを実行してよいか確認する [セキュリティ警告] メッセージ ボックスが表示されます。 [OK] をクリックします。

  6. ソリューション エクスプローラーで、テンプレート ファイル ノードを展開すると、拡張子が .txt のファイルが見つかります。 このファイルには、テンプレートから生成されたテキストが格納されています。

    System_CAPS_ICON_note.jpg メモ

    Visual Basic プロジェクトの場合は、[すべてのファイルを表示] をクリックしないと、出力ファイルが表示されません。

コードの再生成

次のいずれかの場合に、テンプレートが実行され、従属ファイルが生成されます。

  • テンプレートを編集した後、フォーカスを別の Visual Studio ウィンドウに切り替えたとき。

  • テンプレートを保存したとき。

  • [ビルド] メニューの [すべてのテンプレートの変換] をクリックしたとき。 この場合、Visual Studio ソリューション内のすべてのテンプレートが変換されます。

  • ソリューション エクスプローラーで、ファイルのショートカット メニューの [カスタム ツールの実行] をクリックしたとき。 この方法は、複数のテンプレートを選択して変換する場合に使用します。

読み取り先のデータ ファイルが変更されたときにテンプレートが実行されるよう、Visual Studio プロジェクトを設定することもできます。 詳細については、「コードを自動的に再生成する」を参照してください。

テキスト テンプレートから生成されるファイルのコンテンツは、プログラム コードを使用して変化させることができます。

プログラム コードを使用してテキストを生成するには

  1. .tt ファイルの内容を次のように変更します。

    <#@ template hostspecific="false" language="C#" #>  
    <#@ output extension=".txt" #>  
    <#int top = 10;  
    
    for (int i = 0; i<=top; i++)   
    { #>  
       The square of <#= i #> is <#= i*i #>  
    <# } #>  
    
    
  2. .tt ファイルを保存し、生成された .txt ファイルを再度確認します。 0 から 10 の数値を 2 乗した値が一覧表示されます。

複数のステートメントは <#...#> で囲まれており、単一の式は <#=...#> で囲まれていることに注意してください。 詳細については、「T4 テキスト テンプレートの作成」を参照してください。

Visual Basic で生成コードを記述する場合は、template ディレクティブに language="VB" を含める必要があります。 "C#" が既定値です。

テキスト テンプレートをデバッグするには、以下を実行します。

  • debug="true" ディレクティブに template を挿入します。 例:

    <#@ template debug="true" hostspecific="false" language="C#" #>

  • 通常のコードと同じように、テンプレートにブレークポイントを設定します。

  • ソリューション エクスプローラーで、テキスト テンプレート ファイルのショートカット メニューを開き [T4 テンプレートのデバッグ] をクリックします。

テンプレートが実行され、ブレークポイントで停止します。 通常の方法で、変数を調べコードのステップ実行ができます。

System_CAPS_ICON_tip.jpg ヒント

debug="true" は、生成されたコードに行番号ディレクティブを多数挿入して、生成されたコードをテキスト テンプレートに正確に対応付けます。 これを省いた場合、ブレークポイントが間違った状態で実行を停止する可能性があります。

ただし、デバッグしていないときでも、template ディレクティブにこれを残しておくことができます。 こうしても実行速度がほんのわずか低下するだけです。

生成するプログラム ファイルは、モデルに応じて変化させることができます。 モデルは入力です。たとえば、データベース、構成ファイル、UML モデル、DSL モデルなど、各種のソースがそれに該当します。 プログラム ファイルは、同じモデルから複数生成するのが一般的です。 そのためには、生成するプログラム ファイルごとにテンプレート ファイルを作成し、すべてのテンプレートで同じモデルを読み取るようにします。

プログラム コードまたはリソースを生成するには

  1. 適切な種類のファイル (.cs、.vb、.resx、.xml など) を生成するように output ディレクティブを変更します。

  2. 必要なソリューション コードを生成するためのコードを挿入します。 たとえば、クラス内に整数型のフィールド宣言を 3 つ生成するには、次のようにします。

    
                      <#@ template debug="false" hostspecific="false" language="C#" #>  
    <#@ output extension=".cs" #>  
    <# var properties = new string [] {"P1", "P2", "P3"}; #>  
    // This is generated code:  
    class MyGeneratedClass {  
    <# // This code runs in the text template:  
      foreach (string propertyName in properties)   { #>  
      // Generated code:  
      private int <#= propertyName #> = 0;  
    <# } #>  
    }  
    
    
  3. ファイルを保存し、生成されたファイルを調べると、次のコードが含まれていることがわかります。

    class MyGeneratedClass {  
      private int P1 = 0;   
      private int P2 = 0;  
      private int P3 = 0;  
    }  
    
    

生成コードと生成されたテキスト

プログラム コードを生成する際に最も重要なことは、テンプレート内で実行されるコード生成機構 (コードを生成するためのコード) と、結果として生成されるコード (ソリューションの一部になるコード) とを混同しないことです。 2 つの言語が必ずしも一致している必要はありません。

前の例は、2 つのバージョンで構成されています。 1 つ目のバージョンは C# のコードで生成されます。 2 つ目のバージョンは、Visual Basic のコードで生成されます。 ただし、両方のコードで生成されるテキストは同じであり、C# クラスです。

同様に、Visual C# テンプレートは、どのような言語のコードでも生成できます。 生成されるテキストは、プログラム コードが含まれる固有の言語である必要はありません。

テキスト テンプレートの構成

ここでは、テンプレート コードを次の 2 つの部分に分けています。

  • 構成またはデータ収集の部分。この部分では変数に値を設定しますが、テキスト ブロックは含まれません。 前の例では、properties の初期化の部分が該当します。

    この部分はインストア モデルを構築し、通常はモデル ファイルを読み取るため、"モデル" セクションとも呼ばれます。

  • テキスト生成部分 (この例では、foreach(...){...})。この部分では変数の値を使用します。

必ずしもこのように分ける必要はありませんが、このように記述すると、テキストを含む部分の複雑さが軽減され、テンプレートが読みやすくなります。

モデル ファイルまたはモデル データベースにアクセスするために、テンプレート コードで System.XML などのアセンブリを使用できます。 これらのアセンブリにアクセスするためには、次のようなディレクティブを挿入する必要があります。

<#@ assembly name="System.Xml.dll" #>  
<#@ import namespace="System.Xml" #>  
<#@ import namespace="System.IO" #>  

assembly ディレクティブでアセンブリを指定することによって、Visual Studio プロジェクトの [参照設定] セクションに表示されるアセンブリと同じように、指定されたアセンブリにテンプレート コードからアクセスすることができます。 System.dll への参照を含める必要はありません。System.dll は自動的に参照されます。 import ディレクティブの効果は、完全修飾名を使用せずに型を指定できるようになることです。通常のプログラム ファイルで using ディレクティブを使用した場合と同様です。

たとえば、System.IO のインポート後に、次のようなコードを記述できます。

  
          <# var properties = File.ReadLines("C:\\propertyList.txt");#>  
...  
<# foreach (string propertyName in properties) { #>  
...  

相対パス名を指定してファイルを開く

テキスト テンプレートを基準とする場所からファイルを読み込むには、this.Host.ResolvePath() を使用します。 this.Host を使用するには、次のように hostspecific="true"template を設定する必要があります。

<#@ template debug="false" hostspecific="true" language="C#" #>  
  

これで、次のようなコードを記述できるようになります。

<# string fileName = this.Host.ResolvePath("filename.txt");  
  string [] properties = File.ReadLines(filename);  
#>  
...  
<#  foreach (string propertyName in properties { #>  
...  
  

this.Host.TemplateFile を使用して、現在のテンプレート ファイルの名前を示すこともできます。

this.Host (VB の場合は Me.Host) の型は、Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost です。

Visual Studio からデータを取得する

Visual Studio で提供されるサービスを使用するには、hostSpecific 属性を設定し、EnvDTE アセンブリを読み込みます。 その後、IServiceProvider.GetCOMService() を使用して、DTE などのサービスにアクセスできます。 次に例を示します。

<#@ template hostspecific="true" language="C#" #>  
<#@ output extension=".txt" #>  
<#@ assembly name="EnvDTE" #>  
<#  
  IServiceProvider serviceProvider = (IServiceProvider)this.Host;  
  EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));  
#>  
  
Number of projects in this VS solution:  <#= dte.Solution.Projects.Count #>  
  

System_CAPS_ICON_tip.jpg ヒント

テキスト テンプレートは独自のアプリ ドメインで実行され、サービスはマーシャリングによってアクセスされます。 この状況では、GetCOMService() は GetService() よりも信頼性が高くなります。

Visual Studio ソリューションには、1 つの入力モデルを使用して複数のファイルを生成するのが一般的です。 各ファイルはそれぞれ対応するテンプレートから生成されますが、すべてのテンプレートは同じモデルを参照します。

ソース モデルが変更された場合は、ソリューションのすべてのテンプレートを再度実行する必要があります。 これを手動で行うには、[ビルド] メニューの [すべてのテンプレートの変換] をクリックします。

Visual Studio Visualization and Modeling SDK がインストールされている場合は、ビルドを実行するたびにすべてのテンプレートが自動的に変換されるように設定できます。 そのためには、プロジェクト ファイル (.csproj または .vbproj) をテキスト エディターで編集し、ファイルの末尾付近の、他の <import> ステートメントよりも後に次のコード行を追加します。

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\TextTemplating\Microsoft.TextTemplating.targets" />  
<PropertyGroup>  
   <TransformOnBuild>true</TransformOnBuild>  
   <!-- Other properties can be inserted here -->  
</PropertyGroup>  

詳細については、「ビルド処理でのコード生成」を参照してください。

エラー メッセージおよび警告メッセージを Visual Studio のエラー ウィンドウに表示するには、次のメソッドを使用します。

Error("An error message");  
Warning("A warning message");  

テンプレートには、見た目は生成されるファイルとよく似ていて、そこに、プログラム コードが挿入されているという特徴があります。 このことを利用すると、テンプレートを効率的に作成することができます。 最初に通常のファイル (Visual C# ファイルなど) をプロトタイプとして作成し、その後、結果のファイルにバリエーションを持たせるための生成コードを徐々に適用していく方法です。

既存のファイルをデザイン時テンプレートに変換するには

  1. Visual Studio、.cs.vb など、生成する種類のファイルを .resx プロジェクトに追加します。

  2. この新しいファイルをテストして、ファイルが機能することを確認します。

  3. ソリューション エクスプローラーで、ファイル名拡張子を .tt に変更します。

  4. .tt ファイルの次のプロパティを確認します。

    カスタム ツール =TextTemplatingFileGenerator
    ビルド アクション =なし
  5. ファイルの先頭に次の行を挿入します。

    <#@ template debug="false" hostspecific="false" language="C#" #>  
    <#@ output extension=".cs" #>  
    
    

    テンプレートのコード生成機構を Visual Basic で記述する場合は、language 属性を "VB" ではなく、"C#" に設定してください。

    extension 属性を、生成するファイルの種類のファイル名拡張子 (.cs.resx.xml など) に設定します。

  6. ファイルを保存します。

    指定された拡張子の従属ファイルが作成されます。 そのプロパティは、ファイルの種類に対応します。 たとえば、.cs ファイルの [ビルド アクション] プロパティは [コンパイル] になります。

    生成されたファイルのコンテンツが、元のファイルと同じであることを確認します。

  7. ファイルの可変部分を見極めます。 たとえば、特定の条件を満たした場合にのみ出力する部分や、繰り返し出力する部分、特定の値をどこで変化させるかなどを決めます。 コードを生成するためのコードを挿入します。 ファイルを保存し、従属ファイルが正しく生成されたことを確認します。 この手順を繰り返します。

T4 テキスト テンプレートの記述に関するガイドライン」を参照してください。

次の手順トピック
補助的な関数、インクルード ファイル、外部データなどを使用したコードを組み合わせて、より高度なテキスト テンプレートを作成し、デバッグする。T4 テキスト テンプレートの作成
実行時にテンプレートからドキュメントを生成する。T4 テキスト テンプレートを使用した実行時テキスト生成
Visual Studio の外部でテキストの生成を行う。TextTransform ユーティリティを使用したファイルの生成
ドメイン固有言語の形式でデータを変換する。ドメイン固有言語からのコード生成
独自のデータ ソースを変換するためのディレクティブ プロセッサを作成する。T4 テキスト変換のカスタマイズ

T4 テキスト テンプレートの記述に関するガイドライン

表示: