Рекурсивный блок шаблона Т4 - PullRequest
0 голосов
/ 02 февраля 2010

У меня есть функция с именем IterateThroughChildren (), и я хочу написать код для выдачи кода изнутри этой функции.

Обычно блок кода включается в <# #>, а пользовательские функции включаются.внутри <# + #> мы испускаем наш код внутри блока <# = #>.Что, если я хочу рекурсивно выполнить вышеупомянутую функцию и, основываясь на некоторой логике, я хочу выдать код, например

, например,

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

3 голосов
/ 24 октября 2014

Я знаю, что это старый вопрос, но все же хотел поделиться: вы можете избежать использования методов 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);
#>

Наращивание и удаление делегата создает несколько уродливый код, но использование синтаксиса <#...#> между ними имеет много преимуществ.

(я знаю, что пример - это неверный код, но я попытался отразить псевдокод принятого ответа как можно лучше.)

2 голосов
/ 03 февраля 2010

Когда вы используете функциональные блоки класса в 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 (SomeThing) - единственное, что я добавил.

...