Visual Studio 2015高级编程(第6版)
上QQ阅读APP看书,第一时间看更新

14.1 创建T4模板

在Visual Studio的以前版本中,创建新的T4模板是一个隐藏的特性,需要创建扩展名为.tt的文本文件。从Visual Studio 2010以来,创建T4模板只需要从Add New Item对话框的General页面中选择Text Template项,如图14-1所示。

图14-1

创建或保存新的T4模板时,Visual Studio会显示如图14-2所示的警告对话框。T4模板执行正常的.NET代码,在理论上可以用于运行任意类型的.NET代码。每次保存T4模板时,都会执行它,所以可能会多次看到这个警告。有一个选项可以抑制这些警告,但该选项用于所有解决方案中的所有模板。如果关闭了该选项,又需要显示该警告,那么可以在Tools | Options | Text Templating中把Show Security Message改为True,重新激活该选项。

图14-2

创建模板后,它就在Solution Explorer窗口中显示为扩展名为.tt的文件。该模板文件可以展开,列出它生成的文件。每个模板都会生成一个文件,它与模板文件同名,但扩展名不同。图14-3在Solution Explorer窗口中显示了一个模板文件及其生成的文件。

图14-3

如果使用的是VB,只有给项目启用Show All Files,才能看到生成的文件。

生成的文件最初是空的,因为在模板文件中没有定义任何输出。但模板文件不是空的。第一次生成该文件时,它包含如下两行:

      <#@ 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指令在本章的后面讨论,但这里要提及几个有趣的地方。template指令包含一个特性language,它指定模板使用的语言。每个模板文件都可以包含一些生成最终文件的代码语句,这个特性告诉Visual Studio,这些语句将使用何种语言编写。

模板语言对所生成的文件没有影响。可以从使用VB语言的模板中生成C#文件,反之亦然。模板语言默认为当前项目使用的语言,但可以改变。在C#和VB项目中,都支持C#和VB模板。

assembly和import指令用来提供对基本.NET功能的访问,作为模板处理的一部分。这些指令不是必需的,但是经验表明,除了最简单的模板之外,其他模板都会利用它们。

第二个要注意的方面是output指令中的extension特性。所生成文件的名称总是与模板文件名相同,但用这个特性的内容替代.tt扩展名。如果Visual Studio能识别所生成文件的扩展名,则处理该文件的方式就像在Add New Item对话框中创建它一样。尤其是,如果扩展名表示这是一个代码文件,如.cs或.vb,则Visual Studio就把生成的文件添加到项目的生成过程中。

如果改变了模板的输出扩展名,下次运行模板时,就会删除以前生成的文件。只要不编辑生成的文件,就不会出问题。

在模板文件的底部添加一行代码,其中包含单词Hello World,并保存模板。

C#

      <#@ 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" #>
      Hello World

VB

      <#@ template debug="false" hostspecific="false" language="VB" #>
      <#@ assembly name="System.Core" #>
      <#@ import namespace="System.Linq" #>
      <#@ import namespace="System.Text" #>
      <#@ import namespace="System.Collections.Generic" #>
      <#@ output extension=".txt" #>
      Hello World

如前所述,模板每次保存时都会运行,所以生成的文件会用模板的新内容更新。打开生成的文件,会看到单词Hello World。

打开并再次保存每个模板文件,总是可以重新生成该模板文件。另外可以使用Solution Explorer中右击快捷菜单内的Run Custom Tool选项或Project菜单中的Run Custom Tool菜单选项来生成该模板。单击该按钮会转换解决方案中的所有模板。

如果output指令指定的扩展名匹配当前项目的语言,则生成的文件就包含在该项目中。在生成的文件中,声明的类型和成员都有完整的IntelliSense。下面的代码片段显示了一个T4模板和它生成的代码。其中生成的类可以在程序的其他部分访问,一个小控制台应用程序演示了这个过程。

C#

      <#@ template debug="false" hostspecific="false" language="C#" #>
      <#@ output extension=".cs" #>
      namespace AdventureWorks {
        class GreetingManager {
          public static void SayHi() {
            System.Console.WriteLine("Aloha Cousin!");
          }
        }
      }
      namespace AdventureWorks {
        class Program {
          static void Main(string[] args) {
            GreetingManager.SayHi();
          }
        }
      }

VB

      <#@ template debug="false" hostspecific="false" language="VB" #>
      <#@ output extension=".vb" #>
      Public Class GreetingManager
          Public Shared Sub SayHi()
              System.Console.WriteLine("Aloha Cousin!")
          End Sub
      End Class
      Module Module1
        Sub Main()
          GreetingManager.SayHi()
        End Sub
      End Module

尽管应用程序的其余部分可以获得涉及所生成代码的IntelliSense,但T4模板文件本身没有IntelliSense或Visual Studio 2015中的语法突出显示功能。几个第三方编辑器和插件可以为T4提供更丰富的设计功能。

这个示例可以运行,但并没有体现出T4的强大和灵活。这是因为模板完全是静态的。要创建有用的模板,需要更动态的功能。