
14.2 T4构建基块
每个T4模板都由许多影响所生成文件的块组成。第一个例子中的Hello World代码行就是一个Text块。Text块会从模板文件完整地复制到生成的文件中。它们可以包含任意文本,也可以包含其他块。
除了Text块之外,还有3种类型的块:Expression块、Statement块和Class Feature块。这些块都放在特定类型的标记中,以标识它们。Text块是唯一没有特定标记的块。
14.2.1 Expression块
Expression块用于把一些计算出来的值传递到生成的文件中。Expression块一般显示在Text块内部,用<#=和#>标记来表示。下面的模板示例输出了生成文件的日期和时间:
C#
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".txt" #> This file was generated: <#=System.DateTime.Now #>
VB
<#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".txt" #> This file was generated: <#=System.DateTime.Now #>
块中的表达式可以是用template指令指定的模板语言编写的任意有效表达式。每次运行时,模板都会计算该表达式,再对结果调用ToString()。之后把这个值插入到生成的文件中。
14.2.2 Statement块
Statement块用于在运行模板时执行任意语句。Statement块中的代码可以记录模板的执行、创建临时变量,或者从计算机中删除文件,所以需要特别小心。实际上,Statement块中的代码可以包含用模板语言编写的任意有效语句。Statement块一般用于实现模板内部的流控制、管理临时变量,以及与其他系统交互操作。Statement块用<#和#>标记表示,这些标记类似于Expression块的分隔符,但没有等号。下面的例子生成的文件包含一首流行祝酒歌中的全部99行诗句。
C#
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".txt" #> <# for( int i = 99; i > = 1; ) { #> <#=i #> Bottles of Non-alcoholic Carbonated Beverage on the wall <#=i #> Bottles of Non-alcoholic Carbonated Beverage Take one down And pass it around <# if( i-1 == 0 ) { #> There's no Bottles of Non-alcoholic Carbonated Beverage on the wall <# } else { #> There's <#=i-1 #> Bottles of Non-alcoholic Carbonated Beverage on the wall <# } #> <# } #>
VB
<#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".txt" #> <# For i As Integer = 99 To 1 Step -1 #> <#= i #> Bottles of Non-alcoholic Carbonated Beverage on the wall <#= i #> Bottles of Non-alcoholic Carbonated Beverage Take one down And pass it around <# If i - 1 = 0 Then #> There's no Bottles of Non-Alcoholic Carbonated Beverage on the wall. <# Else #> There's <#= i-1 #> Bottles of Non-alcoholic Carbonated Beverage on the wall. <# End If #> <# Next #>
在上面的例子中,Statement块包含了一个Text块,该Text块又包含许多Expression块。使用这3个块类型可以创建出非常强大的模板。
虽然例子中的Statement块包含其他块,但这并不是必需的。在Statement块中,可以使用Write()和WriteLine()方法直接写入生成的文件。下面是使用这个方法的例子。
C#
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".txt" #> <# for( int i = 99; i > 1; i-- ) { WriteLine( "{0} Bottles of Non-alcoholic Carbonated Beverage on the wall", i); WriteLine( "{0} Bottles of Non-alcoholic Carbonated Beverage", i ); WriteLine ( "Take one down" ); WriteLine( "And pass it around" ); if( i - 1 == 0 ) { WriteLine( "There's no Bottles of Non-alcoholic Carbonated Beverage on the wall." ); } else { WriteLine( "There's {0} Bottles of Non-alcoholic Carbonated Beverage on the wall.",i-1); } WriteLine( "" ); } #>
VB
<#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".txt" #> <# For i As Integer = 99 To 1 Step -1 Me.WriteLine("{0} Bottles of Non-alcoholic Carbonated Beverage on the wall", i) Me.WriteLine("{0} Bottles of Non-alcoholic Carbonated Beverage", i) Me.WriteLine("Take one down") Me.WriteLine("And pass it around") If i - 1 = 0 Then WriteLine("There's no Bottles of Non-Alcoholic Carbonated Beverage on the" & _ " wall.") Else WriteLine("There's {0} Bottles of Non-alcoholic Carbonated Beverage on the" & _ " wall.",i-1) End If Me.WriteLine( "" ) Next #>
这两个模板生成的最终结果相同。根据模板,可能会发现某种方法比另一种方法更容易理解。建议在每个模板中仅使用一种方法,以避免混乱。
14.2.3 Class Feature块
T4块的最后一种类型是Class Feature块。该块包含可以在Statement块和Expression块中调用的任意代码,以帮助生成需要的文件。它常常包含定制的格式化代码或重复的任务。Class Feature块使用<#+和#>标记表示,这些标记类似于表示Expression块的标记,但开始标记中的等号变成了加号。下面的模板使用一种典型的财务格式写入−5~5的数字,每个数字都有两位小数,前面还有一个美元符号,负数写成正数,但加上括号。
C#
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".txt" #> Financial Sample Data <# for( int i = -5; i <= 5; i++ ) { WriteFinancialNumber(i); WriteLine( "" ); } #> End of Sample Data <#+ void WriteFinancialNumber(decimal amount) { if( amount < 0 ) Write("(${0:#0.00})", System.Math.Abs(amount) ); else Write("${0:#0.00}", amount); } #>
VB
<#@ template debug="true" hostspecific="false" language="VB" #> <#@ output extension=".txt" #> Financial Sample Data <# For i as Integer = -5 To 5 WriteFinancialNumber(i) WriteLine( "" ) Next #> End of Sample Data <#+ Sub WriteFinancialNumber(amount as Decimal) If amount < 0 Then Write("(${0:#0.00})", System.Math.Abs(amount) ) Else Write("${0:#0.00}", amount) End If End Sub #>
Class Feature块可以包含Text块和Expression块,但不能包含Statement块。此外,一旦遇到Class Feature块,就不允许出现Statement块。
了解到可以出现在模板文件中的不同类型的T4块后,下面看看Visual Studio 2015如何使用它们生成输出文件。