コンテンツへスキップ

QualiArtsengineer blog

テンプレートエンジンT4とRiderを活用したC#コードの自動生成

テンプレートエンジンT4とRiderを活用したC#コードの自動生成

6 min read

サイバーエージェントのゲーム・エンターテイメント事業部(SGE)に所属する子会社QualiArtsでUnityエンジニアをしている住田です。本記事はQualiArtsの定期ブログ「QualiArts Tech Note」第8弾の記事となります。QualiArtsでは会社で使われている様々な技術の知見をブログで紹介しています。興味のある方は他の記事もチェックしてみてください。

はじめに

開発を進めていると、似たようなコードを自動生成したいというケースが存在します。例えばAPI要件に沿った実装の量産だったり、似たような機能のコードの雛形など、コピペや単調なコードの連続で実装する部分を自動生成することで実装コストを減らしたりヒューマンエラーを防ぐことができます。本記事ではそういったコードの自動生成を行う上で有用なT4というテンプレートエンジンと、Unityで開発を行う上で非常に有用なIDEであるRiderを組み合わせた使い方の紹介をします。

本記事で動作検証を行なっているRiderのバージョンは2020.3となっています。そして、RiderのバージョンについてはT4サポートが入った2019.3以降を対象とした記事になっております。

https://blog.jetbrains.com/dotnet/2019/12/17/introducing-t4-text-template-support/

基本的にこの2019.3よりも前のバージョンのRiderでは本記事の紹介する手順が踏めないのでご注意ください。

T4とは

T4とは自動生成テキストテンプレートエンジンの一種で、正式な名称はText Template Transfomration Toolkitです。Visual Studioが公式で提供しているものなので、当然特徴としてVisual Studioとの連携機能が強いという点が挙げられます。新しいファイルの生成時にT4のテンプレートを適用することができたり、テンプレートエンジンの実行に対してブレークポイントを設置してデバッグをしたりすることが可能です。

T4にはザイン時コード生成というテンプレートを元にコードを記述したファイルを生成するタイプと、実行時テキスト生成というパラメータに合わせてコードの文字列を返すようなクラスを生成するタイプの2種類が存在します。ちなみに本記事で触れるのは前者のデザイン時コード生成です。テンプレートファイルの記述についてはC#を使用できます。Unityエンジニアのように、C#を普段活用しているエンジニアにとって同じ感覚でテンプレートの記述ができるのもT4の大きな利点です。

Riderとは

RiderはJet Brains社の提供するクロスプラットフォームの.NET IDEです。
https://www.jetbrains.com/ja-jp/rider/

コード補完やシンタックスハイライト、デバッガといった標準的な機能はもちろんのこと、強力な検索機能やリファクタリング機能など開発に役立つ様々な機能が搭載されています。Unityとの連携もされており、デバッグ実行や任意のスクリプトがアタッチされたPrefabの表示などの機能も用意されています。

QualiArtsではエンジニアの多くがMacで開発を行なっていることと機能性の面からRiderをUnityエンジニアの標準のIDEとして採用しています。Riderの機能の活用ノウハウを社内で共有したり、プロジェクト単位で設定の共有を行ったりしております。本記事ではこのRiderでT4のデザイン時コード生成の実行とそのデバッグを行う手順について紹介します。

RiderでT4を使ってみる

T4ファイルの生成とデザイン時コード生成

まずはT4のファイルを作成します。
下の画像のように右クリックのメニューから追加するファイルの種類で「T4 File」を選択します。

選択したらファイル名を決めてT4 Fileを選択します。

選択すると.ttという拡張子のテンプレートファイルが生成されます。ちなみにT4 includeはテンプレートの記述の中で使用するスニペットを外部定義するためのファイルになります。詳しくはこちらの公式ドキュメントを参照してください。

https://docs.microsoft.com/ja-jp/visualstudio/modeling/t4-include-directive?view=vs-2019

それでは試しにRiderでT4を利用して適当なコードを生成してみます。例として使用するテンプレートファイルの中身を下に示します。

<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<# // あらかじめ定義しておくスニペット、後で呼ぶ
   // メソッドの数
   var number = 5;

   // メソッド名のprefix
   var methodPrefix = "Hoge";

   // メソッド名の生成メソッド、”public void Hoge{n}”のstringを返す
   string GetMethodName(int count)
   {
       // 番号をつけるだけ
       return $"public void {methodPrefix}{count}";
   }

   // 引数の生成メソッド、”(int value1, int value2...)”のstringを返す
   string GetMethodParameter(int count)
   {
       // 個数分の引数をvalue1からvalue10まで連結する
       var parameters = Enumerable.Range(1, count).Select(value => $"int value{value}");
       return $"({string.Join(", ", parameters)})";
   }
#>
<# // ここからが生成するコード // #>
using System.Collections.Generic;
using System.Linq;

namespace TestGenerate
{
   public class SampleClass
   {
<# // 引数が0から5までのメソッドを作る // #>
<# for (int i = 0; i <= number ; i++) {#>
<# // 引数の数であるiを元にメソッド名と引数の文字列を連結する // #>
       <#= GetMethodName(i) #><#= GetMethodParameter(i) #>
       {
           // ここを実装
       }

<# } #>
   }
}

引数が0から5つのHoge0からHoge5という名前のメソッドを生成するテンプレートになります。<#で括られている部分がスニペットで、このテンプレートではメソッド名と引数を返すメソッドを定義し、それらをfor文を使って0から5の引数に対応したコードを生成するように記述をしています。

それではこのテンプレートをもとにコードを生成します。ファイルを右クリックしてRun Templateを実行します。

実行すると以下の同名のファイルが生成されます。テンプレートファイルの記法に間違いがある場合はエラーログが出力されますので確認してください。

using System.Collections.Generic;
using System.Linq;

namespace TestGenerate
{
   public class SampleClass
   {
       public void Hoge0()
       {
           // ここを実装
       }

       public void Hoge1(int value1)
       {
           // ここを実装
       }

       public void Hoge2(int value1, int value2)
       {
           // ここを実装
       }

       public void Hoge3(int value1, int value2, int value3)
       {
           // ここを実装
       }

       public void Hoge4(int value1, int value2, int value3, int value4)
       {
           // ここを実装
       }

       public void Hoge5(int value1, int value2, int value3, int value4, int value5)
       {
           // ここを実装
       }

   }
}

このようにT4とRiderを使うことによって、C#の記法を活用しながら簡単操作でコードを生成することができます。テンプレートファイルも補完やハイライトが効いているため、普段のコーディングと同様の生産性でテンプレートファイルを記述できます。

T4テンプレートのデバッグ

RiderでT4を使う利点にはVisualStudioと同様にデバックの実行を行えるという点もあります。実際に実行例を示しながら説明します。まずはRider上でテンプレートファイル内にブレークポイントを置いてみます。

そして、同じくメニューからデバッグ実行を行います。先ほど選択したメニューのすぐ下にあるのでわかりやすいかと思います。

実行すると、ブレークポイントに対応して一時停止し、変数の値などを確認することができます。下の画像ではGetMethodNameに入ってきている値がRider上に表示されています。

詳細な値の確認やステップ実行などはRiderのデバッグウィンドウで確認できます。もちろんRiderで通常のC#コードの実行を行う際に使用できる各種デバッグ機能も活用可能です。

Riderのデバッグ機能はかなり高機能で、テンプレートエンジンでもこれが活用できるのは便利です。

おわりに

T4というテンプレートエンジンをRiderで活用する方法について説明しました。最近ではUnityでの開発をMacで行う人も多く、Visual StudioでなくともT4を活用できるというのはRiderの大きな利点ではないかなと思います。T4に興味がわいた方や、Riderを使っていてコードの自動生成を行いたいと思っていた方はぜひとも試してみてほしいです。

参考文献

本記事を書くにあたって参考にさせていただいたものになります。

http://neue.cc/2019/12/06_585.html

https://docs.microsoft.com/ja-jp/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2019

2018年にサイバーエージェントに新卒入社。その後、QualiArtsにて新規プロジェクトのUnityエンジニアとして開発に携わる。現在は、運用プロジェクトのUnityリードエンジニアとして従事。ゲーム・エンターテイメント事業部(SGE)全体のUnityの技術促進を目的とする横軸組織「Unityコミュニティ」の責任者としても活動している。