演练:调试文本模板
调试文本模板之前,应了解模板转换过程的两个步骤。 每个步骤中可能会出现不同类别的错误。 步骤如下所示。
文本模板转换引擎创建名为“生成的转换类”的类。 若要创建生成的转换类,文本模板转换引擎必须能够分析文本模板。
在此步骤中,文本模板中的错误(如不正确的标记)可能会阻止对文本模板进行分析。 会使用正确的文本模板行号报告错误。
引擎编译生成的转换类。
在此步骤中,代码错误可能会阻止编译生成的转换类。 会使用正确的文本模板行号报告大多数错误。 模板代码中不匹配的括号可能会导致涉及到转换的类(这些类具有临时文件名)的错误。
执行已编译的转换类以生成输出。
不会使用正确的行号报告此阶段中的错误。 可以逐句执行模板代码,但必须按下节所述显式启动调试器。
若要调试文本模板,必须先更正文本模板中的错误。 随后必须更正生成的转换类中的错误。
提示
转换文本模板时,可能会出现源自以下三个来源中任意来源的错误:文本模板、生成的转换类以及从文本模板中调用的任何指令。 在本演练中,会对文本模板和生成的转换类中的错误进行调试。 但是,也可以使用这些过程调试自定义指令。
本演练演示以下任务:
调试不正确的文本模板标记
逐句通过模板代码
创建文本模板
创建 C# 控制台应用程序项目,并将文本模板添加到解决方案中。 会在后面的步骤中调试此文本模板。
创建文本模板
在 Visual Studio 中,创建新的 C# 控制台应用程序,将其命名为 DebugTemplate。
将名为 DebugTest.tt 的文本模板文件添加到 DebugTemplate 项目。
确保将 DebugTest.tt 的**“自定义工具”**属性设置为 TextTemplatingFileGenerator。
编辑文件,以便仅包含下面一行:
<#@ output extension=".txt" #>
保存该文件。
系统会转换文本模板并生成相应的输出文件。 新文件会在**“解决方案资源管理器”**中出现文本模板文件下。
调试不正确的文本模板标记
编写文本模板时的一个常见语法错误是使用不正确的开始标记或结束标记。 在此过程中,会调试一个不正确的标记。
调试不正确的文本模板标记
将下面的代码添加到 DebugTest.tt 中:
提示
该代码中含有一个错误。 您要引入该错误,以便进行调试。
<# for (int i = 0; i < 3; i++) { > Hello, World! <# } #>
保存该文件。
**“错误列表”**窗口会出现,并显示此错误:
在块中找到意外开始或结束标记。 请确保未错误地键入开始或结束标记并且在模板中不包含任何嵌套的块。
在此例中,代码中的错误为一个不正确的结束标记。 缺少结束标记中的 #。
在**“错误列表”**窗口中双击该错误,以跳转到代码。
若要更正代码,请将 # 添加到结束标记。
<# for (int i = 0; i < 3; i++) { #>
保存该文件。
现在,系统会转换文本模板并生成相应的输出文件。 **“错误列表”**窗口中没有错误。
逐句通过模板代码
若要逐句通过模板代码,需要将两个内容添加到模板:
<@#template debug="true" #>
System.Diagnostics.Debugger.Launch();
在下面的过程中,会调试一个不存在的元素索引。 此错误与前面过程中的错误类似。 但是,这次会使用 Visual Studio 调试器调试该错误。
使用调试器进行调试
创建文件夹“C:\nonsense”,然后将名为“nonsense.xml”的空文本文件保存到该文件夹
用下面的代码替换 DebugTest.tt 中的代码:
提示
该代码中含有一个错误。 您要引入该错误,以便进行调试。
<#@ output extension=".txt" #> <#@ assembly name="System.Xml.dll" #> <#@ import namespace="System.Xml" #> <# XmlDocument xDoc = new XmlDocument(); xDoc.Load(@"C:\nonsense\nonsense.xml"); XmlAttributeCollection attributes = xDoc.Attributes; if (attributes != null) { foreach (XmlAttribute attr in attributes) { #> <#= attr.Name #> <# } } #>
保存该文件。
**“错误列表”**窗口会出现,并显示下面的错误:
运行转换:System.Xml.XmlException:缺少根元素。
添加一个 template 指令,其中 debug 参数设置为 true:
<#@ template debug="true" #>
将一个 System.Diagnostics.Debugger.Launch() 语句添加到文本模板代码。
代码看起来会类似于下面这样:
<#@ template debug="true" #> <#@ output extension=".txt" #> <#@ assembly name="System.Xml.dll" #> <#@ import namespace="System.Xml" #> <# XmlDocument xDoc = new XmlDocument(); System.Diagnostics.Debugger.Launch(); xDoc.Load(@"C:\nonsense\nonsense.xml"); XmlAttributeCollection attributes = xDoc.Attributes; if (attributes != null) { foreach (XmlAttribute attr in attributes) { #> <#= attr.Name #> <# } } #>
再次运行转换。
将显示**“Visual Studio 实时调试器”**对话框。
在**“可能的调试器”列表中,单击“Visual Studio 2010 新实例”,然后单击“是”**。
DebugTest.tt 会在 Visual Studio 的新实例中打开。
逐句通过代码框下面这行:
xDoc.Load(@"C:\nonsense\nonsense.xml");
会在此行上引发错误。
关闭 Visual Studio 的第二个实例。
在**“调试”菜单上,单击“停止调试”**。
在**“文件”菜单上单击“退出”**。
提示您将更改保存到解决方案时,请单击**“否”**。
Visual Studio 的第二个实例会关闭。
修复文本模板并移除调试功能。
在**“解决方案资源管理器”**中,双击 DebugTest.tt 以在编辑器中打开该文件。
修复不正确的文件名。 例如,将其替换为:
@"C:\\Program Files\\Microsoft Visual Studio 10.0\\Xml\\SnippetsIndex.xml"
移除 templat 指令和分隔线。
文本模板应类似于下面这样:
<#@ output extension=".txt" #> <#@ assembly name="System.Xml.dll" #> <#@ import namespace="System.Xml" #> <# XmlDocument xDoc = new XmlDocument(); xDoc.Load(@"C:\Program Files\Microsoft Visual Studio 10.0\Xml\SnippetsIndex.xml"); foreach (XmlNode node in xDoc.SelectNodes("//*")) { #> <#= node.Name #> <# } #>
保存 DebugTest.tt。 验证是否不存在错误,以及生成的 .txt 文件是否列出了 XML 文件中的节点名称。