使用设计时 T4 文本模板,您可以在 Visual Studio 项目中生成程序代码和其他文件。 通常,您编写一些模板,以便它们根据来自模型的数据来改变所生成的代码。 模型是包含有关应用程序要求的关键信息的文件或数据库。

例如,您可能具有一个将工作流定义为表或关系图的模型。 可以从该模型生成执行工作流的软件。 当用户的要求变化时,可以很容易地与用户讨论新的工作流。 从工作流重新生成代码比手动更新代码更可靠。

说明

模型是描述应用程序特定方面的数据源。 它可以是任何形式、任何类型的文件或数据库。 它不必是任何特定形式,例如 UML 模型或域特定语言模型。 典型的模型是表或 XML 文件形式。

您可能已熟悉代码生成。 在 Visual Studio 解决方案中的 .resx 文件内定义资源时,将自动生成一组类和方法。 通过资源文件编辑资源比必须编辑类和方法要更加容易和可靠。 通过文本模板,可以使用相同的方式从自己设计的源中生成代码。

文本模板包含您要生成的文本以及用于生成文本的变量部分的程序代码。 程序代码允许您重复或有条件地省略部分已生成的文本。 生成的文本本身可以是将组成应用程序一部分的程序代码。

创建设计时 T4 文本模板


在 Visual Studio 中创建设计时 T4 模板
  1. 创建一个 Visual Studio 项目或打开一个现有项目。

    例如,在 文件 菜单中,选择 新建,项目。

  2. 添加文本模板文件添加到项目中并为其扩展名为 .tt 的名称。

    为此,请在 解决方案资源管理器,请在项目中快捷菜单上,选择 添加,新建项。 在 添加新项 对话框中选择 文本模板 从中间窗格中。

    请注意,该文件的“自定义工具”属性为“TextTemplatingFileGenerator”。

  3. 打开该文件。 该文件中已包含下列指令:

    复制

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>

    如果已将模板添加到 Visual Basic 项目,则语言特性将为“VB”。

  4. 在文件末尾添加一些文本。 例如:

    复制

    Hello, world!
  5. 保存该文件。

    您可能会看到一个“安全警告”消息框,要求确认要运行该模板。 单击“确定”。

  6. 在 解决方案资源管理器,展开模板文件节点,将查找具有扩展名 .txt 的文件。 文件包含从模板生成的文本。

    说明

    如果项目为 Visual Basic 项目中,必须单击 显示所有文件 才能看到输出文件。

重新生成代码

在下列任何一种情况下,将执行模板,同时生成附属文件:

  • 编辑模板然后转换注意指向的 Visual Studio 窗口。

  • 保存模板。

  • 在 生成 菜单中单击 转换所有模板。 这将转换 Visual Studio 解决方案中的所有模板。

  • 在 解决方案资源管理器,在所有文件快捷菜单上,选择 运行自定义工具。 使用此方法转换模板的所选子集。

还可以设置 Visual Studio 项目,以便在模板读取的数据文件更改时执行这些模板。 有关详细信息,请参阅 自动重新生成代码

生成可变文本


通过文本模板,可以使用程序代码更改已生成文件的内容。

使用程序代码生成文本
  1. 更改 .tt 文件的内容:

    C#

    VB

    复制

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>
    <#int top = 10; for (int i = 0; i<=top; i++) { #>
    The square of <#= i #> is <#= i*i #>
    <# } #>
  2. 保存 .tt 文件,然后重新检查已生成的 .txt 文件。 该文件列出数字 0 到 9 的平方。

请注意,语句括在 <#...#> 内,单个表达式括在 <#=...#> 内。 有关详细信息,请参阅 编写 T4 文本模板

如果在 Visual Basic 中编写生成代码,则 template 指令应包含 language="VB"。 默认值为 "C#"。

调试设计时 T4 文本模板


调试文本模板:

  • 将 debug="true" 插入 template 指令。 例如:

    <#@ template debug="true" hostspecific="false" language="C#" #>

  • 设置在模板中,方式与您为普通代码中的断点。

  • 从文本模板文件的快捷菜单选择在解决方案资源管理器中 调试 T4 模板。

模板将运行和在断点处停止。 可以通过代码检查变量和步骤以常规方式。

提示

debug="true" 更准确地进行生成的代码映射到文本模板,通过插入多个行号指令添加到生成的代码。 如果忽略它,断点可能停止在错误的状态运行的。

即使您不调试,但是,您在模板指令可以将子句中。 这会导致性能的仅非常小的放置。

生成解决方案的代码或资源


可以根据模型生成不同的程序文件。 模型是输入源,如数据库、配置文件、UML 模型、DSL 模型或其他源。 通常从同一模型生成多个程序文件。 为此,可为生成的每个程序文件创建一个模板文件,然后让所有模板读取同一模型。

生成程序代码或资源
  1. 更改输出指令以生成相应类型(如 .cs、.vb、.resx 或 .xml)的文件。

  2. 插入将生成所需解决方案代码的代码。 例如,如果要在一个类中生成三个整数字段声明,则插入以下代码:

    C#

    VB

    复制

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    <# var properties = new string [] {"P1", "P2", "P3"}; #>
    class MyGeneratedClass {
    <#
    foreach (string propertyName in properties)
    { #>
    private int <#= propertyName #> = 0;
    <# } #>
    }
  3. 保存该文件并检查生成的文件,生成的文件现在包含以下代码:

    复制

    class MyGeneratedClass {
    private int P1 = 0;
    private int P2 = 0;
    private int P3 = 0;
    }
生成代码和生成的文本

生成程序代码时,最重要的是避免混淆以下代码:在模板中执行的生成代码,以及随之生成的将成为解决方案一部分的代码。 这两种语言不必相同。

上一个示例具有两个版本。 在一个版本中,生成代码采用 C#。 在另一个版本中,生成代码采用 Visual Basic。 但是这两个版本生成的文本是相同的,都是 C# 类。

通过相同方式,可以使用 Visual C# 模板生成任何语言的代码。 生成的文本不必采用任何特定语言,并且不必是程序代码。

结构化文本模板

作为一种良好做法,我们往往将模板代码分成两部分:

  • 配置或数据收集部分,它在变量中设置值,但不包含文本块。 在上一个示例中,此部分是 properties 的初始化。

    此部分有时称为“模型”部分,因为它会构造一个存储内模型,并且通常读取模型文件。

  • 文本生成部分(示例中的 foreach(...){...}),它使用变量的值。

虽然这不是必要的分离,但是通过这种方式可以降低包括文本的部分的复杂性,从而更便于读取模板。

读取文件或其他源


若要访问模型文件或数据库,模板代码可以使用诸如 System.XML 之类的程序集。 若要获取对这些程序集的访问权限,必须插入如下指令:

复制

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

assembly 指令使指定的程序集可供模板代码使用,方式与 Visual Studio 项目中的“引用”部分相同。 您无需包括对 System.dll 的引用,它是自动引用的。 import 指令允许您使用类型而不使用其完全限定名,方式与普通程序文件中的 using 指令相同。

例如,导入 System.IO 之后,可以编写:

C#

VB

复制

<# var properties = File.ReadLines("C:\\propertyList.txt");#>
...
<# foreach (string propertyName in properties) { #>
...
通过相对路径名打开文件

若要从相对于文本模板的位置加载文件,可以使用 this.Host.ResolvePath()。 若要使用 this.Host,您必须在 template 中设置 hostspecific="true":

复制

<#@ template debug="false" hostspecific="true" language="C#" #>

然后您可以进行编写,例如:

C#

VB

复制

<# string fileName = this.Host.ResolvePath("filename.txt");
string [] properties = File.ReadLines(filename);
#>
...
<# foreach (string propertyName in properties { #>
...

还可以使用 this.Host.TemplateFile,它标识当前模板文件的名称。

this.Host 的类型(在 VB 中是 Me.Host)是 Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost。

从 Visual Studio 获取数据

若要使用提供的服务在 Visual Studio,请设置 hostSpecific 特性并加载 EnvDTE 程序集。 然后可以使用 IServiceProvider.GetCOMService() 访问 DTE 和其他服务。 例如:

复制

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
#> Number of projects in this VS solution: <#= dte.Solution.Projects.Count #>

提示

文本模板在其自己的应用程序域中运行,并且,服务应用程序访问。 在此情形下,GetCOMService() 比 GetService() 可靠。

自动重新生成代码


通常,Visual Studio 解决方案中的多个文件都使用一个输入模型生成。 每个文件从其自己的模板生成,但这些模板全都引用同一个模型。

如果源模型发生更改,则应重新运行该解决方案中的所有模板。 若要手动执行此操作,请选择在 生成 菜单的 转换所有模板。

如果已安装 Visual Studio 可视化和建模 SDK,则可以在每次执行生成时自动转换所有模板。 为此,可在文本编辑器中编辑项目文件(.csproj 或 .vbproj),然后在文件末尾附近(其他任何 <import> 语句之后)添加以下行:

复制

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\TextTemplating\Microsoft.TextTemplating.targets" />
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
<!-- Other properties can be inserted here -->
</PropertyGroup>

有关详细信息,请参阅 生成过程中的代码生成

错误报告


若要在 Visual Studio 错误窗口中放置错误消息和警告消息,可以使用以下方法:

复制

Error("An error message");
Warning("A warning message");

将现有文件转换为模板


模板的一个非常有用的特性是:它们看起来与其生成的文件(加上一些插入的程序代码)非常相似。 这暗示了创建模板的一种有用方法。 首先,创建一个普通的文件(如 Visual C# 文件)作为原型,然后逐步引入可更改所生成文件的生成代码。

将现有文件转换为设计时模板
  1. 对于您的 Visual Studio 项目,添加要生成的类型的文件,例如 .cs、.vb 或 .resx 文件。

  2. 测试新文件以确保其工作。

  3. 在解决方案资源管理器中,将文件扩展名更改为 .tt

  4. 验证 .tt 文件的以下属性:

    自定义工具 =

    TextTemplatingFileGenerator

    生成操作 =

  5. 在文件开头插入以下行:

    复制

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>

    如果要以 Visual Basic 编写模板的生成代码,请将 language 特性设置为 "VB",而不是 "C#"。

    将 extension 特性设置为要生成的文件类型的文件扩展名,例如 .cs、.resx 或 .xml。

  6. 保存该文件。

    将使用指定扩展名创建一个附属文件。 该文件对于相应文件类型具有正确的属性。 例如,.cs 文件的“生成操作”属性将为“编译”。

    验证生成的文件是否包含与原始文件相同的内容。

  7. 确定要更改的文件部分。 例如,一个仅在特定条件下显示的部分、一个重复的部分或特定值会有所变化的部分。 插入生成代码。 保存该文件,然后验证附属文件是否正确生成。 重复此步骤。

使用 T4 文本模板生成设计时代码的更多相关文章

  1. T4 文本模板编写准则

    如果要在 Visual Studio 中生成程序代码或其他应用程序资源,遵守以下一般准则可能非常有帮助. 它们并不是一成不变的规则. 设计时 T4 模板准则 设计时 T4 模板是在设计时在 Visua ...

  2. 编写 T4 文本模板

    文本模板由以下部件组成: 1)指令 - 控制模板处理方式的元素. 2)文本块 - 直接复制到输出的内容. 3)控制块 - 向文本插入可变值并控制文本的条件或重复部件的程序代码. 指令: 指令是控制模板 ...

  3. T4文本模板转换过程

    T4文本模板转换过程将文本模板文件作为输入,生成一个新的文本文件作为输出. 例如,可以使用文本模板生成 Visual Basic 或 C# 代码,还可以生成 HTML 报告. 有三个组件参与这一过程: ...

  4. 一个简单的代码生成器(T4文本模板运用)

    说要写这篇文章有一段时间了,但因为最近各方面的压力导致心情十二分的不好,下班后往往都洗洗睡了.今天痛定思痛,终于把这件拖了很久的事做了.好,不废话了,现在看看"一个简单的代码生成器" ...

  5. Swagger结合mustache模板生成后台接口代码、以及前后台建模代码

    之前项目中使用的的thrift来建模,维护前后台模型以及rest接口,前台使用的是angular2: 但是使用thrift只能生成建模,后台的rest接口的Controller文件还是需要手动去写,一 ...

  6. T4文本模板

    <#...#> 可以包含语句 <#=...#>  用于表达式,提供“输出”操作 <#+ ...> 使用类功能控制块向文本模板添加方法.属性.字段,必须作为文件中最后 ...

  7. T4学习- 2、创建设计时模板

    使用设计时 T4 文本模板,您可以在 Visual Studio 项目中生成程序代码和其他文件. 通常,您编写一些模板,以便它们根据来自模型的数据来改变所生成的代码. 模型是包含有关应用程序要求的关键 ...

  8. CSharpGL(12)用T4模板生成CSSL及其renderer代码

    CSharpGL(12)用T4模板生成CSSL及其renderer代码 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立 ...

  9. T4模板生成文件要点记录

    可以使用 $(variableName) 语法引用 Visual Studio 或 MSBuild 变量(如 $(SolutionDir)),以及使用 %VariableName% 来引用环境变量.介 ...

随机推荐

  1. Python十分钟入门

    [简介] Python是一种动态解释型的编程语言.Python可以在Windows.UNIX.MAC等多种操作系统上使用,也可以在Java..NET开发平台上使用. [特点] 1. Python使用C ...

  2. MapReducer Counter计数器的使用,Combiner ,Partitioner,Sort,Grop的使用,

    一:Counter计数器的使用 hadoop计数器:可以让开发人员以全局的视角来审查程序的运行情况以及各项指标,及时做出错误诊断并进行相应处理. 内置计数器(MapReduce相关.文件系统相关和作业 ...

  3. Machine Learning & Data Mining 资料整合

    机器学习常见算法分类汇总 | 码农网 数据挖掘十大经典算法 | CSDN博客 (内含十个算法具体介绍) 支持向量机通俗导论(理解 SVM 的三层境界)| CSDN博客 (强烈推荐关注博主) 教你如何迅 ...

  4. leetcode@ [343] Integer Break (Math & Dynamic Programming)

    https://leetcode.com/problems/integer-break/ Given a positive integer n, break it into the sum of at ...

  5. HDU ACM Eight

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 解题背景: 看到八数码问题,没有任何的想法,偶然在翻看以前做的题的时候发现解决过类似的一道题,不 ...

  6. cmake编译win下64位obs

    obs是一款开源编码推流工具,简单易用,非常流行.一次项目中,发现本台式机I3处理器下32位obs推流CPU使用率100%.而使用的第三方设备在64位下,性能较好.所以需要编译64位obs并且编译相应 ...

  7. Hibernate之继承映射

    1. Hibernate支持三种继承映射策略: –使用 subclass进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态. –使用 j ...

  8. HDU 1455 http://acm.hdu.edu.cn/showproblem.php?pid=1455

    #include<stdio.h> #include<stdlib.h> #include<math.h> #include<string.h> #de ...

  9. [置顶] 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

  10. 剑指OFFER之二维数组中的查找(九度OJ1384)

    题目描述: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项.斐波那契数列的定义如下: 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入包括一个整数n(1< ...