T4系列文章之三:介绍T4语法

T4语言的语法很简单,可以说一学就会。它不像C#或Java一样有那么多的限制,所以,只要会C#语音,然后再学习一些T4应该注意的地方,那么就OK了。
T4模板的基本结构可以分成5类:指令块(Directive Block)、文本块(Text Block)、代码语句块(Statement Block)、表达式块(Expression Block)和类特性块(Class Feature Block)。

一、指令块(Directive Block)

你只需要记住指令块是以@开头的,比如下面截图中的内容:
这里写图片描述
和ASP.NET页面的引用一样,它们出现在文件头部,通过<#@…#>表示。其中<#@template…#>指令是必须的,用于定义模板的基本属性,比如:编程语言、基于的文化、是否支持调试等等。比较常用的指令还包括用于引用程序集的<#@assembly…#>、用于导入命名空间的<#@import…#>等等。下面逐一介绍主要内容:
1、<#@import #>
这个主要用于引入命名空间,比如:<#@import namespace=“System.Linq”#>。

2、<#@assembly name="[assembly strong name|assembly file name]"#>
顾名思义这个用于引入dll文件,比如:<#@assembly name=“System.Core.dll”#>。不过这里其实没有必要,因为你只要在当前的引用里添加dll文件就OK了。

3、<#@output extension=""#>
这个用于设置你的输出格式,比如:<#@output extension=".cs"#>,那么你输出的就是.cs文件咯。很好理解,Extension是扩展名的意思嘛。

4、<#@template #>
格式:<#@template language=“C#” hostspecific=“true” debug=“true” inherits=“templateBaseClass” culture=“code” compilerOptions=“options”#>
它主要有两个意思:一个指的是写模板所使用的语言,比如:<#@template language=“C#”#>,表示我这个模板是用C#写的。
另一个很重要的特性是:继承。就是把一些公共的方法抽象到父类中,然后就可以在多个模板中进行复用。这个非常有用,我以后会逐步地介绍。比如:<#@template language=“C#” inherits=“BaseTemplate” debug=“true”#>,BaseTemplate是我写的一个公共父类。

5、<#@include file="" #>
这个很有意思,表示在当前模板中包含另一个文件中的内容。先来一个简单的例子:

  1. 新建一个空白的文本模板,命名为MyTextTemplate.tt
  2. 新建一个myText.txt文件,里面写入一些文字:something in myText file
  3. 在MyTextTemplate.tt模板中输入<#@include file=“myText.txt”#>
  4. 然后你就可以在MyTextTemplate.tt中看到myText.txt文件中的一些字符

指明文件/程序集的路径:

  1. $(SolutionDir):当前项目所在解决方案的目录
  2. $(ProjectDir):当前项目所在的目录
  3. $(TargetPath):当前项目编译输出文件的绝对路径
  4. $(TargetDir):当前项目的编译输出目录,即Web项目的bin目录,控制台、类库项目bin目录下的debug或release目录(取决于当前的编译模式)

举个例子:比如我们在E盘根目录新建了一个控制台项目T4Test,解决方案目录为E:\Guo,项目目录为E:\Guo\T4Test,那么此时在Debug编译模式下:
$(SolutionDir)的值为E:\Guo
$(ProjectDir)的值为E:\Guo\T4Test
$(TargetPath)的值为E:\Guo\T4Test\bin\Debug\T4Test.exe
$(TargetDir)的值为E:\Guo\T4Test\bin\Debug

注意事项:

  1. file的路径可以是相对路径、绝对路径
  2. file可以包括环境变量,但它必须用%包起来,比如:<#@include file="%HOMEPATH%"\MyIncludeFile.t4#>
  3. file后面的文件扩展名不能是.tt

如果你的文件需要用.tt结尾,那可以用t4来代替。因为如果你添加了.tt后缀名的文件,VS会自动把当前文件的Custom Tool(自定义工具)属性设定为TextTemplatingFileGenerator。
示例代码一(include在上):

<#@include file="myText.txt"#>

<#var properties = new string[]{"P1","P2","P3"};#>
class GeneratedClass{
<#foreach(string propertyName in properties)
  {#>
    private int <#= propertyName#>=9;
<#}#>
}

示例一代码截图:
这里写图片描述
示例二代码(include在下):

<#var properties = new string[]{"P1","P2","P3"};#>
class GeneratedClass{
<#foreach(string propertyName in properties)
  {#>
    private int <#= propertyName#>=9;
<#}#>
}

<#@include file="myText.txt"#>

示例二代码截图:
这里写图片描述
6、<#@parameter type=“Full.TypeName” name=“ParameterName” #>
parameter指令声明模板代码中从外部上下文传入的值初始化的属性。如果编写调用文本转换的代码,则可以设置这些值。这些值既可以在Session字典中传递,也可以在CallContext中传递。
可以声明任何远程类型的参数。也就是说,类型必须使用SerializableAttribute进行声明,或者必须从MarshalByRefObject派生。这样可以将参数值传递到在其中处理模板的AppDomain中。可以使用以下内容编写文本模板:

<#@template language="C#"#>
<#@parameter type="System.Int32" name="TimesToRepeat"#>
<#for(int i=0; i<TimesToRepeat; i++;){#>
Line<#=i#>
<#}#>

二、文本块(Text Block)

文本块就是直接原样输出的静态文本,不需要添加任何的标签。从指令块结束到第一个“<#”标签之间的内容就是一段静态的文本块,定义在<#…#>、<#+…#>、<#=…#>之间的都不属于文本块。
模板内容:

<#@template language="C#"#>
Hello World!

编译的内容:

using System;
using Microsoft.VisualStudio.TextTemplating;  
 
namespace Microsoft.VisualStudio.TextTemplating413AE4BE2CE28AB99
{
    public class GeneratedTextTransformation: TextTransformation
    {
        public override string TransformText()
        {
            this.Write("Hello World!");
            return this.GenerationEnvironment.ToString();
        }
    }
}

输出的是:Hello World!

三、代码语句块(Statement Block)

代码语句块通过<#…#>的形式来表示,中间是一段使用相应的编程语言编写的程序代码,我们可以通过代码语句块控制文本的转化流程。
由于我们使用的是Asp.Net平台,所以在这里代码语句块的作用主要就是写C#代码,示例如下:

<#for (int i = 0; i < 3; i++)
  {#>
	<#= i #>,
<#}#>
Hello

输出结果如下:
这里写图片描述
凡是我们平时能在VS里写的代码,都可以在<##>里表示。

四、表达式块(Expression Block)

表达式块通过<#=…#>的形式来表示,它可以动态地解析字符串表达式,并输出到相应的文件中,示例如下:

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

<#var properties = new string[]{"P1","P2","P3"};#>
class GeneratedClass{
<#foreach(string propertyName in properties)
  {#>
    private int <#= propertyName#>=9;
<#}#>
}

运行结果截图如下:
这里写图片描述

五、类特性块(Class Feature Block)

类特性块通过<#+…#>的形式来表示,它可以用来定义供调用的方法。
如果文本转化需要一些比较复杂的逻辑,我们需要将其封装成一个单独的方法,甚至是封装成一个单独的类,那就要用到类特性块了,示例如下:

<#@template language="C#"#>
<#HelloWorld();#>
<#HelloWorld();#>
<#+
private void HelloWorld()
{
	this.Write("Hello World1");
	this.WriteLine("Hello World2");
}
#>

运行结果截图如下:
这里写图片描述
不过,您需要注意类特性方法必须放到最后面去,如果你这样用:

<#@template language="C#"#>
<#HelloWorld();#>
<#+
private void HelloWorld()
{
	this.Write("Hello World1");
	this.WriteLine("Hello World2");
}
#>
<#HelloWorld();#>

系统会报错“ErrorGeneratingOutput”,所以大家在使用的时候要特别注意一下:
这里写图片描述
还有就是类特性块里面并不仅仅是一个方法,它里面还可以放很多东西,比如:属性、字段、常量以及可以在编程语言里看到的其他C#结构,我们可以想象一下它的功能有多么强悍,示例如下:

<#HelloWorld();#>
<#+
private string _field="guoguo";
private void HelloWorld()
{	
    for (int i = 0; i < 3; i++)
    {#>
		Hello <#=_field#> World <#=i#>!
    <#+}
}
#>

运行结果截图如下:
这里写图片描述

六、MSDN相关链接

其实对于“T4模板”的学习,讲得最详细的还是MSDN,下面给出对应的链接,有需要的同学可以进行深入的了解。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

changuncle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值