kazuk は null に触れてしまった
C# / .NET 系技術ネタ縛りでお送りしております
csproj.user を作るための T4 テンプレート
2010/08/13
投稿者: : スイカドライブに BuildOptions.tt なるものを投下いたしましたのでご案内。
(またリンクを Spaces が消したら Blog の移転を考えるなう)
デバッグモードを持っていて、デバッグモード時には msbuild を実行してログを取って BuildOptions.txt に吐き出してくれますので、編集して保存(T4 では save is execute なのだよ)の繰り返しでパタパタといじっていけるはずです。デバッグモードでない場合にはこんなのを csproj.user に吐いたよと BuildOptions.txt に吐き出します。
こいつに色々と盛り込まれている 「よく訓練されたT4使いになる為のあれこれ」 をご紹介しましょう。
- よく訓練されたT4使いは 「何を元に作るか」 「何を作るか」 だけを考える。
<# Generate( (何を元に作るか), (o)=>{#> 何を作るか <#} ); #> と書く。
ファイルの最後に飛んで以下のように書く。
<#+
void Generate<T>( IEnumerable<T> seq, Action<T> action )
{
foreach( var item in seq ) { action(item) };
}
#>ポイントは T4 のコードブロック中で (value)=>{#> むにゃむにゃ <#} は立派な Action<T> な statement lambda だという事です。
何を元に作るかはきっと from … select になるでしょう。 何を作るかの中では <#=o.Property#> で値を出力する事ができます。
- よく訓練されたT4使いは TextTemplate クラスの外にコードを置ける
さて、<#@ include filename=""> でこんなファイルを取り込むとします。
<#+ }
// ここはクラスの外!
public partial class 読み込み元のTTのクラス名 { #>
1で作った Generate メソッドを IEnumerable<T> に対する拡張メソッドにするとかそんな事しちゃいけません。ダメ、絶対。
- よく訓練されたT4使いは T4 の Write を殺す
今回はやってませんけど(出力はxmlとtextだし、改行の調整とか必要無いから)、習慣としてファイル末尾で
<#+
public new void Write( string value )
{
GenerationEnvironment.Append( value.Replace( Environment.NewLine, Environment.NewLine+CurrentIndent );
}
#>するほうが良いです。
VS2010 使いの人は CustomTool を GeneratorからPreprocessor に変えると cs ファイルを得る事ができますが、 Base のWrite は色々ごちゃごちゃやっていて結果を想像するのが大変だし、なんだかなーです。 - よく訓練された T4 使いは ToStringHelper に絶望している。
3と似たりよったりですが、partial がついてなかったり、ToStringWithCulture に virtual をMSの中の人が付け忘れたせいで bool は TrueとかFalse とか出るし、null に対して "null" と文字列を出すとかもできません。なんかオブジェクトだすとクラス名だけになっちゃったり。List<T>とか出すと <#@ output extention=".il" #> がお勧めですか!って文字列になります。
- よく訓練された T4 使いは IFormatProvider にも絶望している。
System.Boolean.ToString( IFormatProvider )
解説
provider パラメータは予約されています。このパラメータは、このメソッドの実行には関与しません。
-
(Added 2010/8/15) 良く訓練された T4 使いは脱獄する
-
よく訓練された T4 使いは Preprocessor かけてから Write(ToStringHelper.ToStringWithCulture( を置換する
(もうT4じゃなくなってるという突っ込みは許可しない)
- よく訓練された T4 使いは TextTemplatingFileGenerator をレジストリ検索して…
「HOWTO: Visual Studio のカスタムツールの作り方 (C#) 」ってMSDNドキュメントとか、KBどっかに無いもんか?
まぁ、後半は冗談交じりですがこんな感じです。
VS2010 への移行がらみで CLR2 と CLR4 の両方をターゲットにビルドしたいとか色々ありげな今日この頃、皆様の助けとなる tt であるかなーとかいう事で。TTファイルは以下
( やっぱり消えた、僕の SkyDrive の public にあるからどーぞ )
以下、余談。
そうそう、CLR 4.0 (mscorlib 4.0) で string は真に imuttable になりましたねー
CLR2 の間は「string は imuttable だから」とか書いてあると鼻で笑ってしまう僕だったのですが、もうそんな事も無くなって良いことです。
え? って思ったアナタは mscorlib 2.0 の StringBuilder の Append にデバッガで step-in してみる事をお勧めします。
CLR2.0 においての StringBuilder は「String.AppendInplace へのアクセスヘルパであり、capacity overflow に対する failsafe を提供するクラス」で、String は imuttable でなく repeatly editableだったんですよ。(ΩΩΩΩ< な、なんだってー)
StringBuilder の m_StringValue が無くなった事で動かなくなったコードが(アワワワワ
ちなみに超パフォーマンススペシフィックなシチュエーションに対してよく訓練された .NET er は
public static class StringBuilderExtention
{
/// <summary>
/// ToString と同じ動作だけど、ここでコピーが発生するって事を示す為にワザトextentionする
/// </summary>
public static string CopyString( this StringBuilder sb ) { return sb.ToString(); }
}
とか、コピーを避ける為に m_StringValue を取り出して使うとかしてたりしてなかったり…