一、什么是T4模板
T4是Text Template Transformation Toolkit(文本模板转换工具包)的四个英文首字母的简称。是微软提供的一种代码生成引擎。
在ADO.NET实体数据模型和EF框架中,那些根据数据库表结构自动生成的代码就是根据这种引擎来生成的,所以当我们对VS自动生成的代码不满意或有特殊需求,则可以修改T4模板来达到目的。
在VS2012中,通过下面步骤可以添加T4模板(以.tt为后缀名):
其中“文本模板”和“运行时文本模板”是微软提供的两种T4模板
当添加一个“文本模板”时,新建的文件中默认会有如下代码:
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".txt" #>
二、编写T4文本模板--语法
要学习如何进行T4模板的编写,首先需要了解T4模板的语法。
文本模板由下面三部分组成:
2.1指令
指令通常是模板文件或包含的文件中的第一个元素,其语法一般如下所示:<#@ 指令名 [属性名=”属性值”] … #>
T4模板包含的指令有:模板指令、输出指令、参数指令、程序集指令、导入指令、包含指令
模板指令的一般格式如下:
<#@ template [language="VB"] [hostspecific="true|TrueFromBase"] [debug="true"] [inherits="templateBaseClass"] [culture="code"] [compilerOptions="options"] [visibility="internal"] [linePragmas="false"] #>template指令的所有属性如上所示,这些指令指定了转换的不同方面,并且都是可选的。language属性:有效值是:C#(默认)、VB。 用于指定模板中程序代码所使用的编程语言。hostspecific属性:有效值:true,false(默认),trueFromBase。
若设置为true,则会将名为 Host 的属性添加到由文本模板生成的类中,该属性是对转换引擎的宿主的引用,并声明为 ITextTemplatingEngineHost。
如果已经定义了自定义宿主,则可以将其转换为自定义宿主类型。(关于ITextTemplatingEngineHost的更多内容,请参考:
http://msdn.microsoft.com/zh-cn/library/vstudio/microsoft.visualstudio.texttemplating.itexttemplatingenginehost(v=vs.110).aspx
)
debug属性:有效值:true、false(默认)
如果 debug 特性为 true,则中间代码文件将包含使调试器能够更精确地识别模板中出现中断或异常的位置的信息。对于设计时模板,中间代码文件将写入您的 %TEMP% 目录。
inherits属性:
指定模板的程序代码可以继承自另一个类,这个类也可以从文本模板生成。
parameter 指令声明模板代码中从自外部上下文传入的值初始化的属性。基本语法:<#@ parameter type="Full.TypeName" name="ParameterName" #>
如:<#@ template language="C#" #> <#@ parameter type="System.Int32" name="TimesToRepeat" #> <# for (int i = 0; i < TimesToRepeat; i++) { #> Line <#= i #> <# } #>
output 指令用于定义已转换文件的文件扩展名和编码。基本语法:<#@ output extension=".fileNameExtension" [encoding="encoding"] #>
注:每个文本模板中,不应该有多个output,extension的默认值为”.cs”如:<#@ output extension=".txt" #>
assembly 指令可加载程序集,以便您的模板代码可使用其类型。该作用类似于在 Visual Studio 项目中添加程序集引用。
基本语法:<#@ assembly name="[assembly strong name|assembly file name]" #>,程序集名称应符合下述规范:
GAC 中程序集的强名称,例如 System.Xml.dll。 还可以使用长形式,例如 name="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"。
程序集的绝对路径
import 指令允许您在不提供完全限定名称的情况下引用另一个命名空间中的元素,等效于 C# 中的 using
基本语法:<#@ import namespace="namespace" #>
例如:<#@ import namespace="System.IO" #>
注:System命名空间会自动导入
通过使用 <#@include#> 指令可包括来自另一个文件的文本。基本语法:<#@ include file="filePath" [once="true"] #>
filePath可以是绝对路径,也可以是相对于模板的路径
2.2控制块
用于控制输出的文件内容。包含在<# … #>标记中
例如:
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>
<#
int top = 10;
for(int i=0;i<=top;i++)
{
#>
The square of <#= i #> is <#= i*i #>
<#
}
#>
保存后会输出:
The square of 0 is 0
The square of 1 is 1
The square of 2 is 4
The square of 3 is 9
The square of 4 is 16
The square of 5 is 25
The square of 6 is 36
The square of 7 is 49
The square of 8 is 64
The square of 9 is 81
The square of 10 is 100
表达式控制块用于提供要写入输出文件的字符串的代码,用于变量值的输出。表达式块放于<#= … #>标记中
例如:
The square of <#= i #> is <#= i*i #> 会输出i的值和i*i的值
可以使用类功能控制块向文本模板添加方法、属性、字段甚至是嵌套类。类功能块最常用来为文本模板中其他部件的代码提供帮助器函数。放于<#+ … #>标记中,该标记需放于模板的最后。
例如:
<#+ private int DoubleNumber(int number) { return 2*number; } #>
the double of <#= i #> is <#= DoubleNumber(i) #>
备注:上述三种标记是不能互相嵌套的。只能是完成一个标记后开启先的标记
2.3文本块
不包含与任何标识中的文本,如:this is the content。
2.4文本模板中的工具方法
Write() 和 WriteLine() 方法在标准代码块内追加文本,而不必使用表达式代码块
例如下面的两个代码块
使用表达式块的代码<# int i = 10; while (i-- > 0) { #> <#= i #> <# } #>
使用WriteLine() 的代码块
<# int i = 10; while (i-- > 0) { WriteLine((i.ToString())); } #>
PushIndent() 方法增加缩进;PopIndent() 方法减少缩进;ClearIndent() 方法删除所有缩进。
Error()方法输出错误信息;Warning()方法输出警告信息。如:<# try { string str = null; Write(str.Length.ToString()); } catch (Exception e) { Error(e.Message); } #>2.5 其他
指令名 |
参数说明 |
作用 |
$(ProjectName) |
项目的基本名称 |
获取给定项目的路径 |
$(solutionName) |
解决方案的名称 |
获取给定解决方案的路径 |