T4はC#でC#を作れる便利な子(C#じゃなくてもいいけど)
実装していて迷ったことをメモします。
- Visual studio 2019
- .net 5
開発環境のとり方
何処かのフォルダーに置かれている、CSVだったりXMLだったりExcelだったりをもとに大量にソースコードを生成したい場合などあると思います。
そんな時に例えばVisual studioのソリューションフォルダを取得するには次のような感じにします。
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ output extension=".txt" #>
<#
var serviceProvider = this.Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
var solutionFolder = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
#>
<#=solutionFolder#>
ポイント
hotspecific="true"
⇒Hostを使用するようにします。
EnvDTEを使えるようにする
⇒ここから開発環境情報を取得します。
参考にしたMSDNはココ
https://docs.microsoft.com/ja-jp/visualstudio/modeling/writing-a-t4-text-template?view=vs-2019
インクルードガード
C#をメインにしていると忘れてしまいがちな多重インクルードの防止です。↓
#ifndef HOGE
#define HOGE
#endif
#pragma once
T4でも対策しておかないと多重インクルードで怒られます。
ダメな例
Main.tt
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ include file="file1.ttinclude"#>
<#@ include file="file2.ttinclude"#>
<#@ output extension=".txt" #>
<#
var str1 = ReturnString1("test print1");
var str2 = ReturnString2("test print2");
#>
<#=str1#>
<#=str2#>
file1.ttinclude
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ include file="file2.ttinclude"#>
<#+
static string ReturnString1(string message)
{
return ReturnString2(message);
}
#>
file2.ttinclude
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#+
static string ReturnString2(string message)
{
return message;
}
#>
対策
他のファイルをインクルードしているところに **once="true"**をつけます。
<#@ include file="ファイル名" once="true" #>
ファイル出力したくない場合
カスタムツールTextTemplatingFileGeneratorでT4実行すると<# output extension="xxxx" #>で指定した拡張子でファイルが生成されます。
しかし一つのT4から複数のファイルを生成したかったり、生成するファイルの名前、場所をカスタマイズしたい場合に、T4のファイル生成機能が邪魔になる場合があります。
カスタムツールとして使いたいけどファイル生成は抑制したい。そんな時は拡張子として"/"を指定してやるとファイル生成されなくなります。
<#@ output extension="/" #>
MSDNにはこのような情報はなく、StackOverFlowから見つけました。
https://stackoverflow.com/questions/12909097/t4-templates-generates-unwanted-output-file
複数ファイル出力
(追記予定)