- Visual Studio 2015高级编程(第6版)
- (美)Bruce Johnson
- 1326字
- 2021-03-19 15:26:57
14.5 疑难解答
随着模板文件越来越大、越来越复杂,出错的可能性也会显著增加。错误可能发生在几个主要阶段,每个错误的处理方式都略有区别。尽管T4每次只运行一次这些阶段,但执行模板文件时可能发生任何错误,每次保存文件或构建项目时都会发生这种情况。
对T4模板文件进行任何修改时,最好逐步修改,并常常重新生成,立即回退有问题的修改操作。
14.5.1 设计时错误
可能出错的第一个地方是Visual Studio尝试读取T4模板,并使用它创建临时的.NET类。在图14-4中,Expression块的开始标记中少一个#符号,得到的模板是无效的。图14-4底部的Error List窗口显示,Visual Studio很容易标识出这类问题,它甚至可以正确地确定出错的行号。

图14-4
在设计期间另一种常见的错误类型与指令问题相关。许多情况下,指令的特性出现问题时,就会显示一个警告,并使用默认值。当没有可用的默认值时,如import、include和assembly指令,就生成一个错误。
Visual Studio处理无效指令的一个有趣的例外是output指令的extension特性。如果所提供的值无效,就显示一个警告,但根本不生成输出文件。如果有其他代码依赖输出文件的内容,那么后台编译过程会很快发现一长串难以处理的错误。在尝试修复模板前,通过临时删除模板文件中除template指令和output指令外的所有内容,检查是否生成了输出文件。
14.5.2 编译转换错误
在T4传递途径中,可能发生错误的下一个操作是将包含代码生成器类的临时.NET代码文件编译到程序集中。这里发生的错误一般源自Expression块、Statement块或Class Feature块中的畸形代码。Visual Studio会找出并显示这些错误,但文件和行号引用指的是生成的文件。引擎此时找到的每个错误都加上字符串Compiling Transformation作为前缀,以便识别它们。
修复这些错误的第一步是在template指令中打开Debug模式。这会迫使引擎把用来尝试和编译代码的文件副本放在临时文件夹中。转储这些文件后,双击Error List窗口中的错误行,就会打开临时文件,可以看看发生了什么。因为这是.cs或.vb文件,所以Visual Studio能提供语法突出显示和IntelliSense功能,帮助隔离问题区域。一旦发现了普通问题,就很容易找到并更新模板的相关区域。
打开调试模式生成的另一个文件是.cmdline,它包含T4编译模板时传递给csc.exe或vbc.exe的参数。使用这个文件可以重建编译过程。还有一个扩展名为.out的文件,它包含对编译器的命令行调用及其结果。
14.5.3 执行转换错误
在T4传递路径中,可能发生错误的最后一步是实例化并执行代码生成器,生成输出文件的内容。这个阶段本质上是执行任意.NET代码,最有可能遇到环境条件或错误逻辑问题。与编译转换错误一样,在这个阶段找到的错误有Executing Transformation前缀,很容易识别。
处理Executing Transformation错误的最佳方式是采用防御编码方式。在T4模板中,如果检测到一个错误,如文件缺失或连接不上数据库,就可以使用Error()方法,告诉引擎出了什么问题。与其他错误一样,这些错误也显示Executing Transformation前缀,只是它们有与上下文更相关、更有用的消息:
if( !File.Exists(fileName) ) { this.Error("Cannot find file"); }
除了Error()方法外,还可以使用等价的Warning()方法生成警告。
如果T4模板遇到灾难性错误,如不能连接数据库以获取数据,就可以抛出一个异常,停止执行过程。异常的信息在Error List工具窗口中收集和包含。
14.5.4 生成的代码错误
尽管在技术上不是T4过程的一部分,但生成的文件也很容易包含编译时错误或运行时错误。对于编译时错误,Visual Studio可以像往常那样检测出来。对于运行时错误,可以对复杂的类型进行单元测试(甚至包括已生成的类型)。
现在你已经知道出错时如何处理,下面看一个较大的例子。