2010-02-02 154 views
0

我有一個名爲IterateThroughChildren()的函數,我想編寫代碼以從該函數內部發出代碼。遞歸塊T4模板

通常情況下,代碼塊包含在<##中,並且自定義函數包含在<#+#>中,我們在<#=#>塊中發送我們的代碼。我想發出的代碼,如果我想遞歸執行上述功能是什麼,並根據一些邏輯即

<# 
    //Code to get child and parent data 
    IterateThroughChildren(object child, object parent); 
#> 

<#+ 
void IterateThroughChildren(object c, object p) 
{ 
if(c is abc) 
{ 
    if(p is def) 
    { 
    //emit some code here i.e WriteLine(SomeThing); ????? 
    foreach (var item in def.Item) 
    { 
    IterateThroughChildren(item, def); 
    } 

    } 
} 

. 
. 
. 

//and so on 

} 

#> 

回答

2

當您使用T4類的功能塊,即<#+ #>,那麼代碼將成爲生成模板輸出文件的基礎類的一部分。在Visual Studio 2008中,該基礎類派生自抽象類Microsoft.VisualStudio.TextTemplating.TextTransformation

因此,可以通過使用繼承寫()的WriteLine()方法直接寫入到輸出流。例如,在你的代碼:

<# 
    //Code to get child and parent data 
    IterateThroughChildren(object child, object parent); 
    #> 

    <#+ 
    void IterateThroughChildren(object c, object p) 
    { 
    if(c is abc) 
    { 
    if(p is def) 
    { 
    //emit some code here i.e WriteLine(SomeThing); ????? 
    this.WriteLine(SomeThing); // writes SomeThing to the output file 
    foreach (var item in def.Item) 
    { 
    IterateThroughChildren(item, def); 
    } 

    } 
    } 

. . . 

//and so on 

} 

#> 

其中this.WriteLine(東西)是我說的唯一的事。

2

我知道這是一個老問題,但還是想和大家分享:你可以通過使用完全避免使用Write()WriteLine()方法的Action<>

<# 
    Action<object,object> IterateThroughChildren = null; // null to avoid compile-time error 
    IterateThroughChildren = delegate(object c, object p) 
    { 
     if(c is abc) 
     { 
      if(p is def) 
      { 
#> 
// Emit some code here. No WriteLine() or Write() needed! 
<# 
      } 

      foreach (var item in def.Item) 
      { 
       IterateThroughChildren(item, def); 
      } 
     } 
    } 

    //Code to get child and parent data 
    IterateThroughChildren(child, parent); 
#> 

的積累和委託的拆除造成有些醜陋的代碼,但在中間使用<#...#>語法有很多優點。

(我知道該示例是錯誤的代碼,但我試圖儘可能反映接受的答案的僞代碼。)