2012-10-29 9 views
8

私はかなり複雑なものをT4テンプレートに詰め込んでいます。基本的に私は...T4コードをもっときれいにするためにそこに何かありますか?

{= FOO =}複数のテキストのようなものを取る

などのようなクラス(ビュー)に変換:

public class MyView 
{ 
    public string foo{get;set;} 
    public string Write() 
    { 
    return [email protected]" more text..."; 
    } 
} 

生成コードされますもちろんそれよりはるかに複雑です。とにかく、T4テンプレートは現在600行以上のコードであり、本当に管理不能になっています。私は主な問題は、コードと "コンテンツ"(つまり、静的コード)を混ぜることだと考えています。私は本当にこの問題をきちんと修正する方法はわかりません(生成されたコードには影響しません)。私はT4コードの単体テストを実現する方法も見当たりません。単にT4の実行エラーをテストするだけです。もちろん、生成されたコードをテストすることはほとんど不可能な作業であるようです。

T4テンプレートコードをよりきれいにするために使用できる「モデルビュー」タイプのフレームワークまたはテクニックはありますか?これは、最小(メンテナンス上の問題の多くの場合、原因)にテンプレートロジックを維持するのに役立ちます -

+0

これはオプションではないかもしれませんが、私は[Resharper Templates](http://www.jetbrains.com/resharper/features/code_templates.html)をT4テンプレートより優先します。また、[Resharper](http://www.jetbrains.com/resharper/)は他の用途にも優れたツールです。コストの価値がある – TylerOhlsen

+2

Resharperは良いツールですが、Resharper TemplatesとT4を比較したIMHOはリンゴとオレンジを比較しています。 Resharperテンプレートは、ツールのサポートでコピー・ペースト・アンチ・パターンを促進し、管理しなければならないコードがますます冗長化され、メンテナンスのコストが増加します。 T4(および他のツール)は、コードアーチファクト(大量のリダンダンシーを伴う)を生成するメタプログラム(冗長度が低い)を書くという点で、冗長性を最小限にします。重要なのは、メタプログラムと生成されたコードとの間のカジュアルな接続が失われないということです。 – FuleSnabel

答えて

1

長い旅の後、私は最終的に私のT4テンプレートに最初の単体テストをチェックインしました。基本的に、私は "ビュー"(実際のT4テンプレート)と "ロジック"(コードを生成するものの、実際には出力せず、T4に依存しない)を抽象化しています。

Iこれをさらに進めて、hackという大きな文字を使って、ロジックファイルをT4の外でコンパイルするようにしました。これはインテリセンスとコンパイラのエラーがうまく働くようにする効果がありました。また、プロジェクトを参照するだけで、単体テストからロジッククラスにアクセスすることもできます。

コードサンプル(前/後)とサンプルユニットテストon my blogで完全な記事を書いています。

5

私見二つの最も重要な概念の複雑なテンプレートを書くときには、モデルとビューを分離

  1. です。個人的に私はこれがフレームワークを必要としないと思っています。
  2. 私は部分的にあなたの友人です - 私は一般的にモデルからスケルトンコードを生成するためにT4を使用します。特定の振る舞いは、モデルに入れる努力の価値がないかもしれませんが、部分的なクラスやメソッドを使用してその振る舞いが出るようにするほうがよくあります。

として重要であるが良くない

  1. コードが検索してください - 私は十分にそれらのどれもが良い見つけるので、私はナビゲートするために、インテリセンスの欠如と、T4のアドオンに依存しません私はコードを検索可能にする必要があります。 ColumnプロパティNameを呼び出すのではなく、ColumnNameという名前で呼び出すことができます。
  2. 出力に「tags」を挿入します。 - 出力のその部分を生成したコードを簡単に見つけることができます。

例分離モデル/ビュー:

<# 
    // Model for Dependency Pooperties 
    Model = new [] 
    { 
     new ClassDefinition ("MyDataGrid") 
      { 
       P ("CultureInfo"   , "CultureInfo"), 
       P ("Pen"     , "CellBorderPen"), 
       P ("IEnumerable<object>" , "Rows"), 
       C ("WColumnDefinition"  , "Columns"), 
      }, 
    }; 
#> 
// Include the view 
<#@ include file="..\T4\DependencyProperties.ttinclude" #> 

ビュー、モデルを反復処理と依存性を生成します。依存関係プロパティの

挙動は、部分メソッドとしてモデルにこの特定の動作を置くことは著しくモデルが複雑になること

partial void Changed_Columns(
     ObservableCollection<WColumnDefinition> oldValue, 
     ObservableCollection<WColumnDefinition> newValue 
     ) 
    { 
     HookUpColumns(oldValue, null); 
     HookUpColumns(newValue, this);    
    } 

注実現されます。

最後に、有能なプログラマーがメタプログラムを有能に書いても時間がかかります。それは私が維持できると信じているスタイルに到着する前に私はいくつかの試みが必要でしたが、私にとっては、私がより速く品質を出荷できるように努力する価値がありました。私はこれが役に立てば幸い

...

PS。私は誰もT4が今までエレガントだと主張するだろうと考えているが、それでもそれは有用である。

+0

私は実際には "モデル"を通常のアセンブリに分割し、実際にコード生成を処理してからT4コードを正規アセンブリにリンクする単純なT4 "ビュー"を持っていると考えました。ユニットテストの合併症 – Earlz

+0

私は、少なくとも「ユニット」テストを行うための「良い」方法を見つけたと思います。これは「ビュー」と「モデル」の厳密な分離も強制します。詳細をすべて整理すると、ここに投稿しますが、基本的には、生成されたT4出力に含まれる異なる '.cs'ファイルに「モデル」が含まれています。それは完璧ではありませんが、それは今までに見つけた最高です – Earlz

+1

私はこれをやってどうやって私の[自己解答](http://stackoverflow.com/a/13486081/69742)インテリセンス、コンパイラエラー、単体テストがT4テンプレートで使用されているロジックで動作します – Earlz

関連する問題