文本模板控制块

使用控制块,可以在文本模板中编写代码以便改变输出。 有三种类型的控制块,根据其左括号对它们进行区分:

  • <# 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);
       }
     }  
#>

您可以在诸如 if 或 for 等的复合语句内嵌入纯文本。 例如,此片段会在每一个循环迭代中生成一个输出行:

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

警告

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

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

应该包括 {括号},如下所示:

 
<#
 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 string 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#,但可以使用 template 指令的 language 参数指定 Visual Basic。 (有关 template 指令的更多信息,请参见T4 文本模板指令。)

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

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

  • **局部变量。**因为文本模板中的标准控制块和表达式控制块中的所有代码都是作为一个方法生成的,所以应确保局部变量的名称不会冲突。 如果包含其他文本模板,必须确保变量名在所有包含的模板中是唯一的。 确保唯一性的一种方法是向每个局部变量名添加一个字符串,用于标识声明该变量的文本模板。

    在声明局部变量时(特别是在包含多个文本模板时),将它们初始化为合理的值也是一个很好的方法。

  • **控制块的嵌套。**控制块不能互相嵌套。 必须先终止给定控制块,然后才能打开另一个。 例如,下面演示如何将表达式块中的部分文本输出为标准控制块的一部分。

    <# 
    int x = 10;
    while (x-- > 0)
    {
    #>
    <#= x #>
    <# } #>
    
  • **重构。**为保持文本模板简短并易于理解,强烈建议避免编写重复的代码,方法是将可重用的代码重构到类功能块中的帮助器函数,或创建您自己的从 Microsoft.VisualStudio.TextTemplating.TextTransformation 类继承的文本模板类。