使用设计时 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. <转>亲手缔造DNS体系,创建DNS私有根:DNS系列之六

    打造DNS私有根 我们现在已经从前面的博文中了解到了很多DNS的相关知识,今天我们用一个综合性的实验把前面的内容都串起来复习一下,这个有趣的实验就是DNS的私有根.私有根顾名思义是由个人或企业自行创建 ...

  2. 使用C语言实现二维,三维绘图算法(1)-透视投影

    使用C语言实现二维,三维绘图算法(1)-透视投影 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其实想想 ...

  3. oracle修改密码及账户锁定

    在oracle修改密码的时候,一种是用dba账户来修改用户的密码,一种是用户自己修改自己的密码: SQL> alter user kel identified by kel; 解锁命令: SQL ...

  4. 基于Python的Grib数据可视化

    http://www.cnblogs.com/kallan/p/5160017.html

  5. PHP实现分页:文本分页和数字分页

    来源:http://www.ido321.com/1086.html 最近,在项目中要用到分页.分页功能是经常使用的一个功能,所以,对其以函数形式进行了封装. // 分页分装 /** * $pageT ...

  6. WeChat Official Account Admin Platform API Introduction

    Keyword: WeChat API Introduction Message and GeneralAuthor: PondBay Studio[WeChat Developer EXPERT] ...

  7. Kindle Paperwhite 2使用体验

    博客开通后一懒就扔下了几十天,着实自惭.鉴于是第一篇,先说点题外话. 一转眼读研的生活已经过去一年有余.曾经的同学已经在职场拼搏,同龄人的生活状态也自然地带给自己一份紧迫感:不敢再贪恋校园生活的安逸, ...

  8. Ubuntu 12.04 安装wine1.7

    从源码安装wine 我的系统环境:ubuntu 12.04.4 X64 wine版本:wine-1.7.12.tar.bz2 解压:tar -xvf wine-1.7.12.tar.bz2 进入win ...

  9. UVA 11300 Spreading the Wealth

    题目大意:n个人手中有些金币,每个人可给相邻两个人一些金币,使得最终每个人手中金币数相同,求被转手的金币最少数 m为最终每个人手中的金币数,a1,a2,a3,...,an为每个人开始时手中的金币数,x ...

  10. Timus OJ 1997 Those are not the droids you're looking for (二分匹配)

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1997 这个星球上有两种人,一种进酒吧至少玩a小时,另一种进酒吧最多玩b小时. 下面n行是 ...