文本模板控制块

使用控制块可以在文本模板中编写代码,以便改变输出。 有三种类型的控制块,其通过开括号来区分:

  • <# Standard control blocks #> 可以包含语句。

  • <#= Expression control blocks #> 可以包含表达式。

  • <#+ Class feature control blocks #> 可以包含方法、字段和属性。

标准控制块

标准控制块包含语句。 例如,以下标准块获取 XML 文档中所有属性的名称:

<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System.Xml" #>

<#
    List<string> allAttributes = new List<string>();
    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(@"E:\CSharp\Overview.xml");
    XmlAttributeCollection attributes = xDoc.Attributes;
    if (attributes.Count > 0)
    {
       foreach (XmlAttribute attr in attributes)
       {
           allAtributes.Add(attr.Name);
       }
     }
#>

可以在复合语句(如 iffor)中嵌入纯文本。 例如,此片段在每个循环迭代中生成一个输出行:

<#
       foreach (XmlAttribute attr in attributes)
       {
#>
Found another one!
<#
           allAtributes.Add(attr.Name);
       }
#>

警告

始终使用 {...} 分隔包含嵌入纯文本的嵌套语句。 以下示例可能无法正常工作:

<# if (ShouldPrint) #> Some text. -- WRONG

相反,应包括 {braces},如下所示:


<#
 if (ShouldPrint)
 {   //  "{" REQUIRED
#>
Some text.
<#
 }
#>

表达式控制块

表达式控制块用于提供要写入输出文件的字符串的代码。 例如,使用上面的示例,可以通过修改代码块将属性的名称输出到输出文件,如下所示:

<#
    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(@"E:\CSharp\Overview.xml");
    XmlAttributeCollection attributes = xDoc.Attributes;
    if (attributes != null)
    {
       foreach (XmlAttribute attr in attributes)
       {
#><#= attr.Name #><#
       }
    }
#>

类特性控制块

可以使用类功能控件块向文本模板添加方法、属性、字段,甚至嵌套类。 类功能块的最常见用法是为文本模板的其他部分的代码提供帮助程序函数。 例如,下面的类功能块将属性名称的第一个字母大写(或者,如果该名称包含空格,则它将每个单词的第一个字母大写):

<#@ import namespace="System.Globalization" #>
<#+
    private string FixAttributeName(string name)
    {
        return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name);
    }
#>

注释

类功能控制块不得遵循同一模板文件中的标准控制块。 但是,此限制不适用于 <#@include#> 指令的结果。 每个包含的文件可以有标准模块,后跟类特性模块。

可以通过在类功能控制块中嵌入文本和表达式块来创建生成输出的函数。 例如:

<#+
    private void OutputFixedAttributeName(string name)
    {
#>
 Attribute:  <#= CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name) #>
<#+  // <<< Notice that this is also a class feature block.
    }
#>

可以从标准块或其他类功能块调用此函数:

<# foreach (Attribute attribute in item.Attributes)
{
  OutputFixedAttributeName(attribute.Name);
}
#>

如何使用控制块

单个模板中的所有标准控件块和表达式控件块中的所有代码(包括包含模板中的所有代码)都组合在一起,形成 TransformText() 生成的代码的方法。 (有关通过 include 指令包含其他文本模板的详细信息,请参阅 T4 文本模板指令。)

使用控制块时,应考虑以下注意事项:

  • 语言。 可以在文本模板中使用 C# 或 Visual Basic 代码。 默认语言是 C#,但可以通过指令中的language参数指定使用 Visual Basic。 (有关该指令的详细信息 template ,请参阅 T4 文本模板指令

    在控件块中使用的语言与在文本模板中生成的文本的语言或格式无关。 可以使用 Visual Basic 代码生成 C#,反之亦然。

    在给定的文本模板中只能使用一种语言,包括指令中包含的 include 所有文本模板。

  • 局部变量。 由于文本模板中的标准和表达式控件块中的所有代码都是作为单个方法生成的,因此应确保与局部变量的名称没有冲突。 如果包括其他文本模板,则必须确保所有包含的模板中的变量名称都是唯一的。 确保这样做的一种方法是向每个本地变量名称添加一个字符串,用于标识声明该字符串的文本模板。

    在声明局部变量时,最好将局部变量初始化为合理的值,尤其是在包括多个文本模板时。

  • 控制块嵌套。 控制块可能不会相互嵌套。 在打开另一个控制块之前,必须始终终止给定的控制块。 例如,下面演示如何将表达式块中的某些文本打印为标准控制块的一部分。

    <#
    int x = 10;
    while (x-- > 0)
    {
    #>
    <#= x #>
    <# } #>
    
  • 重构。 为使文本模板保持简短且易于理解,强烈建议通过将可重用代码分解为类功能块中的帮助程序函数或创建继承自 Microsoft.VisualStudio.TextTemplating.TextTransformation 类的你自己的文本模板类来避免重复代码。