2023年7月3日发(作者:)
⼀、代码⽣成器系列-T4模板学习整理⼀、T4简介T4(Text Template Transformation Toolkit)在 Visual Studio 中,“T4 ⽂本模板”是由⼀些⽂本块和控制逻辑组成的混合模板,它可以⽣成⽂本⽂件。 在 Visual C# 或 Visual Basic 中,控制逻辑编写为程序代码的⽚段。⽣成的⽂件可以是任何类型的⽂本,例如⽹页、资源⽂件或任何语⾔的程序源代码。T4 ⽂本模板有两种类型:
1、运⾏时模板 可在应⽤程序中执⾏运⾏时 T4 ⽂本模板(“预处理过的”模板)以便⽣成⽂本字符串(通常作为其输出的⼀部分)。
若要创建运⾏时模板,请向您的项⽬中添加“已预处理的⽂本模板”⽂件。
另外,您还可以添加纯⽂本⽂件并将其“⾃定义⼯具”属性设置为“TextTemplatingFilePreprocessor”。 2、设计时模板
在 Visual Studio 中执⾏设计时 T4 ⽂本模板,以便定义应⽤程序的部分源代码和其他资源。
通常,您可以使⽤读取单个输⼊⽂件或数据库中的数据的多个模板,并⽣成⼀些 .cs、.vb 或其他源⽂件。
每个模板都⽣成⼀个⽂件。 在 Visual Studio 或 MSBuild 内执⾏它们。
若要创建设计时模板,请向您的项⽬中添加“⽂本模板”⽂件。 另外,您还可以添加纯⽂本⽂件并将其“⾃定义⼯具”属性设置为“TextTemplatingFileGenerator”。⼆、编写第⼀个T4模板例⼦-HelloWorld通过最简单的HelloWorld例⼦,来了解⼀下T4的基本结构
1、在项⽬中【添加新项】:2、模板⽂件代码:<#@ template debug="false" hostspecific="false" language="C#" #><#@ assembly name="" #><#@ import namespace="" #><#@ import namespace="" #><#@ import namespace="c" #><#@ output extension=".cs" #>using System;namespace HelloWorld{ public class HelloWorldMain { public static void Main(string[] args) { <#
List
2). ⽂本块(Text Block)
3). 码语句块(Statement Block)
4). 表达式块(Expression Block)
5). 类特性块(Class Feature Block)1、指令块(Directive Block)和页⾯的指令⼀样,它们出现在⽂件头,通过<#@…#>表⽰。其中<#@ template …#>指令是必须的,⽤于定义模板的基本属性,⽐如编程语⾔、基于的⽂化、是否⽀持调式等等。⽐较常⽤的指令还包括⽤于程序集引⽤的<#@ assembly…#>,⽤于导⼊命名空间的<#@ import…#>等等。指令通常是模板⽂件或包含的⽂件中的第⼀个元素。不应将它们放置在代码块 <#…#> 内,也不应放置在类功能块 <#+…#> 之后。T4 模板指令<#@ template [language="C#"] [hostspecific="true"] [debug="true"] [inherits="templateBaseClass"] [culture="code"] [compilerOptions="options"] #>1.模版指令中所有特性均为可选的。
age:输出语⾔,有效值C#、VB,默认为C#。
:是否启⽤调试,有效值true、false,默认为false。特别说明下这个调试真的不咋地,很容易让VS崩溃,很鸡肋的功能。
ecific:有效值true、false,默认为false。如果将此特性的值设置为 true,则会将名为 Host 的属性添加到由⽂本模板⽣成的类中。 该属性是对转换引擎的宿主的引⽤,并声明为emplatingEngineHost。
ts:可以指定模板的程序代码可以继承⾃另⼀个类,这个类也可以从⽂本模板⽣成。⽬前⽊有使⽤过,基本上可以忽略。
erOptions:有效值为任何有效的编译器选项。基本上可以忽略 。T4 参数指令
<#@ parameter type="me"name="ParameterName"#>
- type:有效值是传递参数的类型名。
- name:传递参数的名。T4 输出指令
<#@ output extension=".fileNameExtension"[encoding="encoding"] #>
⽐较重要的指令,⽤于设置输出⽂件的后缀名和⽂件编码。
- extension:输出⽂件扩展名,默认为”.cs”。
- encoding:⽂件编码。T4 程序集指令
<#@ assembly name="[assembly strong name|assembly file name]"#>
1.程序集指令相当于VS⾥⾯我们添加程序集引⽤的功能,该指令只有⼀个参数name,⽤以指定程序集名称,如果程序集已经在GAC⾥⾯注册,那么只需要写上程序集名称即可,如<#@ assembly name=”” #>,否则需要指定程序集的物理路径。
2.T4模版的程序集引⽤是完全独⽴的,也就是说我们在项⽬中引⽤了⼀些程序集,然后项⽬中添加了⼀个T4模版,T4模版所需要的所有程序集引⽤必须明确的在模版中使⽤程序集执⾏引⽤才可以。
3.T4模版⾃动加载以下程序集mplating.1*.dll、、,如果⽤到了其它的程序集需要显⽰的使⽤程序集添加引⽤才可以。
4.可以使⽤ (variableName)语法引⽤VisualStudio或MSBuild变量(如 (SolutionDir)),以及使⽤ %VariableName% 来引⽤环境变量。介绍⼏个常⽤的$(variableName) 变量: - $(SolutionDir):当前项⽬所在解决⽅案⽬录 - $(ProjectDir):当前项⽬所在⽬录 - $(TargetPath):当前项⽬编译输出⽂件绝对路径 - $(TargetDir):当前项⽬编译输出⽬录,即web项⽬的Bin⽬录,控制台、类库项⽬bin⽬录下的debug或release⽬录(取决于当前的编译模式) - $(SolutionDir):当前项⽬所在解决⽅案⽬录 - $(ProjectDir):当前项⽬所在⽬录 - $(TargetPath):当前项⽬编译输出⽂件绝对路径 - $(TargetDir):当前项⽬编译输出⽬录,即web项⽬的Bin⽬录,控制台、类库项⽬bin⽬录下的debug或release⽬录(取决于当前的编译模式) 举个例⼦:⽐如我们在D盘根⽬录建⽴了⼀个控制台项⽬TestConsole,解决⽅案⽬录为D:LzrabbitRabbit,项⽬⽬录为 D:LzrabbitRabbitTestConsole,那么此时在Debug编译模式下 - $(SolutionDir)的值为D:LzrabbitRabbit - $(ProjectDir)的值为D:LzrabbitRabbitTestConsole - $(TargetPath)值为D: - $(TargetDir)值为D:LzrabbitRabbitTestConsolebinDebug 举个例⼦:⽐如我们在D盘根⽬录建⽴了⼀个控制台项⽬TestConsole,解决⽅案⽬录为D:LzrabbitRabbit,项⽬⽬录为 D:LzrabbitRabbitTestConsole,那么此时在Debug编译模式下 - $(SolutionDir)的值为D:LzrabbitRabbit - $(ProjectDir)的值为D:LzrabbitRabbitTestConsole - $(TargetPath)值为D: - $(TargetDir)值为D:LzrabbitRabbitTestConsolebinDebugT4 导⼊指令
<#@ import namespace="namespace"#>
在 Visual Studio T4 ⽂本模板的代码块中,import 指令允许您在不提供完全限定名称的情况下引⽤另⼀个命名空间中的元素。 它等效于C# 中的 using 或 Visual Basic 中的 imports。默认已经导⼊了System命名空间的引⽤。T4 包含指令
<#@ include file="filePath"#>
th 可以是绝对的,或相对于当前模板⽂件。
th 可以包括⽤“%”分隔的环境变量。 例如:<#@ include file=”%HOMEPATH%MyIncludeFile.t4” #>
3.所包含的⽂件的名称不必使⽤扩展名“.tt”。可能需要针对包含的⽂件使⽤其他扩展名,例如,“.t4”。 这是因为,在您将 .tt ⽂件添加到项⽬中时,Visual Studio 会⾃动将其“⾃定义⼯具”属性设置为 TextTemplatingFileGenerator。 您通常不希望单独转换包含的⽂件。
4.在处理时,被包含内容就像是包含⽂本模板的组成部分⼀样。 不过,即使 include 指令后为普通⽂本块和标准控制块,也可以包括含有类功能块 <#+…#> 的⽂件。
5.包含指令可以提⾼代码复⽤率,⽐如我们可以将⼀些常⽤的程序集、命名空间引⽤放到⼀个⽂件⾥,使⽤时仅需要引⽤下即可,省去了每次都要重新引⽤⼀遍的烦恼,如我们建⽴ude⽂件,⾥⾯包含了我们平时常⽤的程序集引⽤。<# for(int i = 0; i < 4; i++) { Write(i + ", "); } Write("4");#> Hello!您可以交错⽂本和代码,⽽不必使⽤显式 Write() 语句。 以下⽰例输出“Hello!”四次:<# for(int i = 0; i < 4; i++) {#>Hello!<# }
#>在代码中,可以使⽤ Write(); 语句的位置都可以插⼊⽂本块。表达式控制块:
表达式控制块计算表达式并将其转换为字符串。 该字符串将插⼊到输出⽂件中。
表达式控制块以 <#= … #> 符号分隔。
例如,如果使⽤下⾯的控制块,则输出⽂件包含“5”:
<#= 2 + 3 #>
请注意,开始符号有三个字符“<#=”。
表达式可以包含作⽤域中的任何变量。 例如,下⾯的块输出数字⾏:<#@ output extension=".txt" #><# for(int i = 0; i < 4; i++) {#>This is hello number <#= i+1 #>: Hello!<# }
#>类功能控制块:
类功能控制块定义属性、⽅法或不应包含在主转换中的所有其他代码。 类功能块常⽤于编写帮助器函数。通常,类功能块位于单独的⽂件中,这样它们可以包含在多个⽂本模板中。
类功能控制块以 <#+ … #> 符号分隔。
例如,下⾯的模板⽂件声明并使⽤⼀个⽅法:<#@ output extension=".txt" #>Squares:<# for(int i = 0; i < 4; i++) {#> The square of <#= i #> is <#= Square(i+1) #>.<# }
#>That is the end of the list.<#+ // Start of class feature blockprivate int Square(int i){ return i*i;}#>5、类特性块(Class Feature Block)如果⽂本转化需要⼀些⽐较复杂的逻辑,我们需要写在⼀个单独的辅助⽅法中,甚⾄是定义⼀些单独的类,我们就是将它们定义在类特性块中。类特性块的表现形式为<#+ FeatureCode #>,对于Hello World模板,得到⼈名列表的GetUserList⽅法就定义在类特性块中。(上⾯类功能控制块中有描述)T4⽂本模板编写是T4模板运⽤的基础,掌握了这些简单的编写规则后,我们就可以编写基于T4模板的代码⽣成器了
发布者:admin,转转请注明出处:http://www.yc00.com/news/1688384082a129940.html
评论列表(0条)