T4系列文章之3:T4语法的介绍

T4语言的语法很简单,可以说一学就会。它不像C#或者JAVA一样,那么多的限制什么的。所以,只要会C#语言,然后再学习一点T4它应该注意的地方,那么就OK了。

是不是很心动了?心动不如行动吧。

T4模板的基本结构: 它们基本上可以分成5类:指令块(Directive Block)、文本块(Text Block)、代码语句块(Statement Block)、表达式块(Expression Block)和类特性块(Class Feature Block)。

你看上面的截图,把一些基本的都罗列出来了。

1、指令块(Directive Block)

首先,值需要记住的是 指令块是已@开头的。 比如你看到的下面。

和ASP.NET页面的指令一样,它们出现在文件头,通过<#@…#>表示。其中<#@ template …#>指令是必须的,用于定义模板的基本属性,比如编程语言、基于的文化、是否支持调式等等。比较常用的指令还包括用于程序集引用的<#@ assembly…#>,用于导入命名空间的<#@ import…#>等等。

它主要包括以下内容:

1. <#@ import#>

开头,这个主要表示是说引入命名空间 比如:<#@ import namespace="System.Linq" #>

2. <#@ assembly name="[assembly strong name|assembly file name]" #>

顾名思义 指的是 引入ddl文件,比如<#@ assembly name="System.Core.dll" #>。不过这里其实没有必要,因为你只要在当前的引用里添加dll文件就ok了。 3. <#@ output extension="" #>

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

5. <#@ template  #>

格式:<#@ template [language="VB"] [hostspecific="true"] [debug="true"] [inherits="templateBaseClass"] [culture="code"] [compilerOptions="options"] #>

它主要有2个意思:一个只的是写模板所使用的语言,比如<#@ template  language="C#" #> 那么我这个模板可以用C#来些。

另一个很重要的特性指的是:继承。就是把一些公共的方法抽象到父模板中,然后可以在多个模板中进行复用。这个非常有用,我以后会逐步的介绍。 比如:<#@ template language="C#" inherits="CommonTemplate" debug="true" #> CommonTemplate是我写的一个公共模板。

6. <#@ include file="" #>

这个很有意思,意思就是说在当前的模板中包含另外一个文件中的内容。先来一个很简单的例子。

  6.1 新建一个空白的文本模板 ,命名为:MyTextTemplate.tt

  6.2 在新建一个 txt文件,里面写入一些字。myText.txt

  6.3 在MyTextTemplate.tt模板中,<#@ include file=”myText.txt”#>

  6.4  然后你就可以在MyTextTemplate.tt看到 你文本中的一些字符。

    对第六点需要的注意事项:

  1. file的路径可以是绝对路径、相对路径。

    2.file可以包括环境变量,但它必须用%包起来。比如<#@ include file="%HOMEPATH%\MyIncludeFile.t4" #>

    3.file后面的文件的扩展名不能包括 .tt结尾的。

如果你需要用.tt的结尾,你需要用4t来代替。这是因为如果你加了.tt后缀的文件名,因为vs会自动是把当前.tt的文件的Custom Tool(自定义工具)属性设定为TextTemplatingFileGenerator。

2、文本块(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!

3、代码语句块(Statement Block)

代码语句块通过<#Statement#>的形式表示,中间是一段通过相应编程语言编写的程序调用,我们可以通过代码语句快控制文本转化的流程。

其实在我们的使用中,对语句块的作用主要就是写C#代码。

比如,请看下面:

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

 那么输出的结果就是

0,1,2,3,4

Hello!

凡是能在平时我们VS里面书写的代码,都可以在<# #>里表示。

4、表达式块(Expression Block)

表达式块以<#=Expression#>的形式表示,通过它之际上动态的解析的字符串表达内嵌到输出的文本中。

模板内容:

?
<#@ template language= "C#" #>
<#
    for ( int i = 1; i <= 3; i++)
    {
#>
Hello World <#= i #>!
<#
    }
#>

 请注意这个:<#= i #>

后台编译的内容:

?
using System;
using Microsoft.VisualStudio.TextTemplating; 
namespace Microsoft.VisualStudio.TextTemplating76E036EA7C70CB236
{
   public class GeneratedTextTransformation: TextTransformation
   {
      public override string TransformText()
      {
         for ( int i = 1; i <= 3; i++)
         {
            this .Write( "Hello World " );
            this .Write(ToStringHelper.ToStringWithCulture(i));
            this .Write( "!\r\n" );
         }
         return this .GenerationEnvironment.ToString();
       }
   }
}

  输出的内容就是:

Hello World 1!
Hello World 2!
Hello World 3!

5、类特性块(Class Feature Block)

首先我们需要记住的是 类型性模块是有个+号的,比如<#+ #>这种类型的。  

如果文本转化需要一些比较复杂的逻辑,我们需要写在一个单独的辅助方法中,甚至是定义一些单独的类,我们就是将它们定义在类特性块中。类特性块的表现形式为<#+ FeatureCode #>,对于Hello World模板,得到人名列表的InitializePersonList方法就定义在类特性块中。

其实说白了 就是在里面写方法,方便我们多次重用和调用,提高我们的开发效率。

比如:

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

 注意上面的+号的上面有个<# HelloWorld(); #> 。

所以,结果理所当然的就是有2个Hello World。

不过,您需要注意的是,你的这个类特性方法应该放到最后面去,比如你这样用:

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

  

不好意思,它会给你报错,

ErrorGeneratingOutput

因为你不是放到最后面了,所以这里需要特别特别特别注意一下。

还有就是类特性的功能里面并 不仅仅只是一个方法,它里面还可以放很多东西,比如属性、常量、字段以及其他可以在其他编程里看到的C#结构都可以插入里面,我们足足可以见到它有多么强悍的生命力。

比如下面在举一个例子:

?
<#@ template language= "C#" #>
<# HelloWorld(); #>
<#+
    private string _field = "classy" ;
    private void HelloWorld()
    {
        for ( int i = 1; i <= 3; i++)
        {
#>
Hello <#=_field#> World <#= i #>!
<#+
        }
    }
#>

  

输出的结果就是:

Hello classy World 1!

Hello classy World 2!

Hello classy World 3!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值