编写 T4 文本模板Writing a T4 Text Template

文本模板包含将从其生成的文本。A text template contains the text that will be generated from it. 例如,用于创建网页的模板将包含 " <html> ..."以及 HTML 页的所有其他标准部分。For example, a template that creates a web page will contain "<html>..." and all the other standard parts of an HTML page. 插入到模板中的是 控制块,它们是程序代码的片段。Inserted into the template are control blocks, which are fragments of program code. 控制块提供变化值,允许文本部件是条件和重复的。Control blocks provide varying values and allow parts of the text to be conditional and repeated.

使用这一结构很容易开发模板,因为可以以生成文件为原型,然后逐步插入用于改变结果的控制块。This structure makes a template easy to develop, because you can start with a prototype of the generated file, and incrementally insert control blocks that vary the result.

文本模板由以下部件组成:Text templates are composed of the following parts:

  • 指令 -控制如何处理模板的元素。Directives - elements that control how the template is processed.

  • 文本块 -直接复制到输出的内容。Text blocks - content that is copied directly to the output.

  • 控制块 -将变量值插入到文本中并控制文本的有条件或重复部分的程序代码。Control blocks - program code that inserts variable values into the text, and controls conditional or repeated parts of the text.

若要尝试本主题中的示例,请将它们复制到模板文件中,如 使用 T4 文本模板的设计时代码生成中所述。To try the examples in this topic, copy them into a template file as described in Design-Time Code Generation by using T4 Text Templates. 编辑模板文件后,保存该文件,然后检查输出 .txt 文件。After editing the template file, save it, and then inspect the output .txt file.

指令Directives

文本模板指令向文本模板化引擎提供关于如何生成转换代码和输出文件的一般指令。Text template directives provide general instructions to the text templating engine about how to generate the transformation code and the output file.

例如,下面的指令指定输出文件应具有 .txt 扩展名:For example, the following directive specifies that the output file should have a .txt extension:

<#@ output extension=".txt" #>

有关指令的详细信息,请参阅 T4 文本模板指令For more information about directives, see T4 Text Template Directives.

文本块Text blocks

文本块直接向输出文件插入文本。A text block inserts text directly into the output file. 文本块没有特殊格式。There is no special formatting for text blocks. 例如,下面的文本模板将生成一个包含单词“Hello”的文本文件:For example, the following text template will produce a text file that contains the word "Hello":

<#@ output extension=".txt" #>
Hello

控制块Control blocks

控制块是用于转换模板的程序代码节。Control blocks are sections of program code that are used to transform the templates. 默认语言是 C#,但若要使用 Visual BasicVisual Basic,可以在文件开头编写以下指令:The default language is C#, but to use Visual BasicVisual Basic, you can write this directive at the beginning of the file:

<#@ template language="VB" #>

用于编写控制块代码的语言与生成的文本的语言无关。The language in which you write the code in the control blocks is unrelated to the language of the text that is generated.

标准控制块Standard control blocks

标准控制块是生成输出文件部件的程序代码节。A standard control block is a section of program code that generates part of the output file.

在模板文件中,可以混合使用任意数量的文本块和标准控制块。You can mix any number of text blocks and standard control blocks in a template file. 但是,不能在控制块中嵌套控制块。However, you cannot place one control block inside another. 每个标准控制块都以 <# ... #> 符号分隔。Each standard control block is delimited by the symbols <# ... #>.

例如,如果使用下面的控制块和文本块,则输出文件包含行“0, 1, 2, 3, 4 Hello!”:For example, the following control block and text block cause the output file to contain the line "0, 1, 2, 3, 4 Hello!":

<#
    for(int i = 0; i < 4; i++)
    {
        Write(i + ", ");
    }
    Write("4");
#> Hello!

你可以交错文本和代码,而不必使用显式 Write() 语句。Instead of using explicit Write() statements, you can interleave text and code. 下面的示例将打印 "Hello!"The following example prints "Hello!" 四次:four times:

<#
    for(int i = 0; i < 4; i++)
    {
#>
Hello!
<#
    }
#>

在代码中,可以使用 Write(); 语句的位置都可以插入文本块。You can insert a text block wherever a Write(); statement would be allowed in the code.

备注

在复合语句(如循环或条件)中嵌入文本块时,始终使用大括号 {...}When you embed a text block within a compound statement such as a loop or conditional, always use braces {...} 包含文本块。to contain the text block.

表达式控制块Expression control blocks

表达式控制块计算表达式并将其转换为字符串。An expression control block evaluates an expression and converts it to a string. 该字符串将插入到输出文件中。This is inserted into the output file.

表达式控制块以 <#= ... #> 符号分隔。Expression control blocks are delimited by the symbols <#= ... #>

例如,如果使用下面的控制块,则输出文件包含“5”:For example, the following control block causes the output file to contain "5":

<#= 2 + 3 #>

请注意,左符号包含三个字符 "< # ="。Notice that the opening symbol has three characters "<#=".

表达式可以包含作用域中的任何变量。The expression can include any variable that is in scope. 例如,下面的块输出数字行:For example, this block prints lines with numbers:

<#@ output extension=".txt" #>
<#
    for(int i = 0; i < 4; i++)
    {
#>
This is hello number <#= i+1 #>: Hello!
<#
    }
#>

类功能控制块Class feature control blocks

类功能控制块定义属性、方法或不应包含在主转换中的所有其他代码。A class feature control block defines properties, methods, or any other code that should not be included in the main transform. 类功能块常用于编写帮助器函数。Class feature blocks are frequently used for helper functions. 通常情况下,类功能块放在单独的文件中,以便可以将它们 包含 在多个文本模板中。Typically, class feature blocks are placed in separate files so that they can be included by more than one text template.

类功能控制块以 <#+ ... #> 符号分隔。Class feature control blocks are delimited by the symbols <#+ ... #>

例如,下面的模板文件声明并使用一个方法:For example, the following template file declares and uses a method:

<#@ output extension=".txt" #>
Squares:
<#
    for(int i = 0; i < 4; i++)
    {
#>
    The square of <#= i #> is <#= Square(i+1) #>.
<#
    }
#>
That is the end of the list.
<#+   // Start of class feature block
private int Square(int i)
{
    return i*i;
}
#>

类功能必须编写在文件末尾。Class features must be placed at the end of the file in which they are written. 不过,即使 <#@include#> 指令后跟标准块和文本,也可以 include 包含类功能的文件。However, you can <#@include#> a file that contains a class feature, even if the include directive is followed by standard blocks and text.

有关控制块的详细信息,请参阅 文本模板控制块For more information about control blocks, see Text Template Control Blocks.

类功能块可以包含文本块Class feature blocks can contain text blocks

可以编写生成文本的方法。You can write a method that generates text. 例如:For example:

List of Squares:
<#
   for(int i = 0; i < 4; i++)
   {  WriteSquareLine(i); }
#>
End of list.
<#+   // Class feature block
private void WriteSquareLine(int i)
{
#>
   The square of <#= i #> is <#= i*i #>.
<#+
}
#>

将文本生成方法放置在可供多个模板包含的单独文件中,是非常有用的。It is particularly useful to place a method that generates text in a separate file that can be included by more than one template.

使用外部定义Using external definitions

程序集Assemblies

模板的代码块可以使用定义了最常用 .NET 程序集(如 System.dll)的类型。The code blocks of your template can use types that are defined the most frequently used .NET assemblies such as System.dll. 此外,也可以引用其他 .NET 程序集或你自己的程序集。In addition, you can reference other .NET assemblies or your own assemblies. 你可以提供程序集的路径或强名称:You can provide a pathname, or the strong name of an assembly:

<#@ assembly name="System.Xml" #>

应该使用绝对路径名,或在路径名中使用标准宏名。You should use absolute path names, or use standard macro names in the path name. 例如:For example:

<#@ assembly name="$(SolutionDir)library\MyAssembly.dll" #>

Assembly 指令对 预处理文本模板无效。The assembly directive has no effect in a preprocessed text template.

有关详细信息,请参阅 T4 Assembly 指令For more information, see T4 Assembly Directive.

命名空间Namespaces

import 指令与 C# 中的 using 子句或 Visual Basic 中的 imports 子句相同。The import directive is the same as the using clause in C# or the imports clause in Visual Basic. 通过该指令,不使用完全限定名就可以在代码中引用类型:It allows you to refer to types in your code without using a fully qualified name:

<#@ import namespace="System.Xml" #>

可以根据需要使用任意多个 assemblyimport 指令。You can use as many assembly and import directives as you want. 必须将它们放在文本块和控制块之前。You must place them before text and control blocks.

有关详细信息,请参阅 T4 Import 指令For more information, see T4 Import Directive.

包括代码和文本Including code and text

include 指令插入其他模板文件的文本。The include directive inserts text from another template file. 例如,下面的指令插入 test.txt 的内容。For example, this directive inserts the content of test.txt.

<#@ include file="c:\test.txt" #>

在处理时,被包含内容就像是包含文本模板的组成部分一样。The included content is processed almost as if it were part of the including text template. 不过,即使 include 指令后跟普通文本块和标准控制块,也可以包含编写有类功能块 <#+...#> 的文件。However, you can include a file that contains a class feature block <#+...#> even if the include directive is followed by ordinary text and standard control blocks.

有关详细信息,请参阅 T4 Include 指令For more information, see T4 Include Directive.

实用工具方法Utility methods

在控制块中,有几个方法(如 Write())始终可用。There are several methods such as Write() that are always available to you in a control block. 这些方法包括可帮助缩进输出和报告错误的方法。They include methods for helping you indent the output, and for reporting errors.

你也可以编写自己的实用工具方法集。You can also write your own set of utility methods.

有关详细信息,请参阅 文本模板实用工具方法For more information, see Text Template Utility Methods.

转换数据和模型Transforming Data and Models

对于文本模板而言,最有用的应用是根据源(如模型、数据库或数据文件)的内容生成材料。The most useful application for a text template is to generate material based on the content of a source such as a model, database, or data file. 模板提取数据并重新设置数据格式。Your template extracts and reformats the data. 模板集合可以将此类源转换为多个文件。A collection of templates can transform such a source into multiple files.

有几种方法可以读取源文件。There are several approaches to reading the source file.

读取文本模板中的文件Read a file in the text template. 下面是将数据读入模板的最简单的方法:This is simplest way to get data into the template:

<#@ import namespace="System.IO" #>
<# string fileContent = File.ReadAllText(@"C:\myData.txt"); ...

将文件作为可导航模型加载Load a file as a navigable model. 更有效的方法是将数据作为模型读取,文本模板代码可以导航该模型。A more powerful method is to read the data as a model, which your text template code can navigate. 例如,可以加载 XML 文件,然后使用 XPath 表达式对其导航。For example, you can load an XML file and navigate it with XPath expressions. 你还可以使用 xsd.exe 创建一组可用于读取 XML 数据的类。You could also use xsd.exe to create a set of classes with which you can read the XML data.

在关系图或窗体中编辑模型文件。Edit the model file in a diagram or form. 域特定语言工具Domain-Specific Language Tools 提供使您可以将模型作为关系图或 Windows 窗体进行编辑的工具。provides tools that let you edit a model as a diagram or Windows form. 这样便于与生成的应用程序的用户讨论模型。This makes it easier to discuss the model with users of the generated application. 域特定语言工具Domain-Specific Language Tools 还会创建一组反映模型结构的强类型类。also creates a set of strongly-typed classes that reflect the structure of the model. 有关详细信息,请参阅 从域特定语言生成代码For more information, see Generating Code from a Domain-Specific Language.

设计时模板中的相对文件路径Relative file paths in design-time templates

设计时文本模板中,如果要引用相对于文本模板的位置中的文件,请使用 this.Host.ResolvePath()In a design-time text template, if you want to reference a file in a location relative to the text template, use this.Host.ResolvePath(). 还必须在 hostspecific="true" 指令中设置 templateYou must also set hostspecific="true" in the template directive:

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="System.IO" #>
<#
 // Find a path within the same project as the text template:
 string myFile = File.ReadAllText(this.Host.ResolvePath("MyFile.txt"));
#>
Content of MyFile.txt is:
<#= myFile #>

还可以获取主机提供的其他服务。You can also obtain other services that are provided by the host. 有关详细信息,请参阅 从模板访问 Visual Studio 或其他主机For more information, see Accessing Visual Studio or other Hosts from a Template.

设计时文本模板在单独的 AppDomain 中运行Design-time Text Templates run in a separate AppDomain

应注意, 设计时文本模板 在与主应用程序分离的 AppDomain 中运行。You should be aware that a design-time text template runs in an AppDomain that is separate from the main application. 在大多数情况下这并不重要,但在某些复杂的情况下你可能会发现一些限制。In most cases this is not important, but you might discover restrictions in certain complex cases. 例如,如果要从单独的服务将数据传入模板或从中传出数据,则该服务必须提供可序列化的 API。For example, if you want to pass data in or out of the template from a separate service, then the service must provide a serializable API.

(这种情况并不适用于 运行时文本模板,它提供与代码的其余部分一起编译的代码。 ) (This isn't true of a run-time text template, which provides code that is compiled along with the rest of your code.)

编辑模板Editing Templates

可从扩展管理器联机库下载专用文本模板编辑器。Specialized text template editors can be downloaded from the Extension Manager Online Gallery. 在 " 工具 " 菜单上,单击 " 扩展管理器"。On the Tools menu, click Extension Manager. 单击 " 联机库",然后使用搜索工具。Click Online Gallery, and then use the search tool.

任务Task 主题Topic
编写模板。Writing a template. T4 文本模板编写准则Guidelines for Writing T4 Text Templates
使用程序代码生成文本。Generate text by using program code. 文本模板结构Text Template Structure
在 Visual Studio 解决方案中生成文件。Generate files in a Visual Studio solution. 使用 T4 文本模板生成设计时代码Design-Time Code Generation by using T4 Text Templates
在 Visual Studio 外部运行文本生成。Run text generation outside Visual Studio. 使用 TextTransform 实用工具生成文件Generating Files with the TextTransform Utility
以域特定语言的形式转换数据。Transform your data in the form of a domain-specific language. 从域特定语言生成代码Generating Code from a Domain-Specific Language
编写指令处理器转换自己的数据源。Write directive processors to transform your own data sources. 自定义 T4 文本转换Customizing T4 Text Transformation