2012-10-29 59 views
8

我有一個相當複雜的東西塞進T4模板。基本上我採取類似有沒有什麼可以讓T4代碼更清晰?

{=富=}多個文本...

並將其轉換成一個類(視圖)像這樣:

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

生成的代碼是當然比這更復雜。無論如何,T4模板現在已經超過600行代碼,真正變得難以管理。我認爲主要問題是混合代碼和「內容」(即靜態代碼)。我不確定如何徹底解決這個問題,雖然(當然不影響生成的代碼)。我也沒有看到任何可行的方法來單元測試我的T4代碼,除了簡單地測試T4執行錯誤。當然,似乎幾乎不可能測試它生成的代碼。

是否有任何「模型視圖」類型的框架或技術,我可以使我的T4模板代碼更乾淨?

恕我直言編寫複雜的模板時,最重要的兩個概念
+0

這可能不是一個選項,但我更喜歡通過T4模板的[Resharper模板](http://www.jetbrains.com/resharper/features/code_templates.html)。此外,[resharper](http://www.jetbrains.com/resharper/)也是一款令人驚喜的工具,可用於其他用途。這是值得的成本。 – TylerOhlsen

+2

Resharper是一個很好的工具,但恕我直言,比較Resharper模板與T4是比較蘋果和橙子。 Resharper模板正在推廣使用工具支持的複製粘貼反模式,導致您必須維護越來越多的冗餘代碼,從而增加了維護成本。 T4(和其他工具)最大限度地減少了冗餘,因爲你編寫了一個元程序(它具有低冗餘度),可以生成代碼僞像(具有大量的減少量)。關鍵是元程序和生成的代碼之間的偶然連接不會丟失。 – FuleSnabel

回答

1

經過漫長的旅程,我終於在第一次單元測試中檢查了我的T4模板。基本上,我所做的是抽象出一個「視圖」(實際的T4模板)和「邏輯」(生成代碼的東西,但並不實際輸出它並且不依賴於T4)

I然後再深入一步,並使用一個大的hack來讓我的邏輯文件在T4之外編譯。這具有使智能感知和編譯器錯誤起作用的良好效果。它還允許我通過簡單引用該項目從單元測試訪問我的邏輯類。

我寫了一篇完整的代碼示例(之前/之後)和示例單元測試on my blog的文章,如果您想了解如何做到這一點的冗長細節。

5

  1. 分離的模型和視圖 - 這有助於保持模板邏輯降至最低(經常的維護問題的原因)。我個人認爲這不需要一個框架,它只需要你這樣做。
  2. 部分是你的朋友 - 我一般使用T4來從模型生成骨架代碼。具體的行爲可能不值得投入模型,更經常地通過使用部分類或方法來允許這種行爲。

不是很重要,但很好

  1. 使代碼搜索 - 我不以航行靠T4附加組件,因爲我覺得他們沒有足夠好,再加上缺乏智能感知的代碼我必須使代碼可搜索。它可以像調用Column屬性名稱一樣簡單,我稱之爲ColumnName。
  2. 在輸出中插入「標籤」 - 更容易找到生成該部分輸出的代碼。

實施例分離模型/視圖:

<# 
    // 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

好的,我想我發現了一種「好」的方式來至少做單元測試,這也迫使「視圖」和「模型」嚴格分離。當我把所有的細節都整理出來的時候,我會在這裏發佈,但基本上它涉及到將不同的'.cs'文件中的「模型」包含到生成的T4輸出中。這不是完美的,但它是迄今爲止我找到的最好的 – Earlz

+1

你可能想看看我的[自我回答](http://stackoverflow.com/a/13486081/69742)我是如何結束這樣做的,使我的T4模板使用的邏輯工作的intellisense,編譯器錯誤和單元測試 – Earlz

相關問題