调试 T4 文本模板

可以在文本模板中设置断点。 若要调试设计时文本模板,请保存文本模板文件,然后在解决方案资源管理器中的文件的快捷菜单上选择 “调试 T4 模板 ”。 若要调试运行时文本模板,只需调试它所属的应用程序。

若要调试文本模板,应了解模板转换过程的步骤。 每个步骤中都可能发生不同类型的错误。 步骤如下所示。

步骤 设计时模板:生效时 运行时模板:何时发生
代码是从文本模板生成的。

指令中的错误,或<#...#>标签不匹配或无序。
保存模板或调用文本转换时。 保存模板或调用文本转换时。
生成的代码已编译。

模板代码中的编译错误。
紧接在上一步之后。 以及应用程序代码。
代码运行。

模板代码中的运行时错误。
紧接在上一步之后。 当您的应用程序运行并调用模板代码时。

在大多数情况下,模板代码中的行号在错误报告中给出。 当错误报告引用临时文件名时,通常的原因是文本模板代码中的括号不匹配。

可以在文本模板中设置断点,并采用常规方式进行调试。

常见错误和修复

下表列出了最常见的错误及其修复。

错误消息 Description 解决方案
无法加载转换类继承的基类“{0}”。 如果在模板指令中找不到参数中指定的基类, inherits 则会发生此事件。 该消息提供模板指令的行号。 请确保指定的类存在,并且该类存在于程序集指令中。
无法检索文件中包含的文本:{0} 在找不到包含的模板时发生。 该消息提供请求的包含文件的名称。 请确保文件路径相对于原始模板路径,或者该文件位于向主机注册的位置,或者该文件具有文件的完整路径。
初始化转换对象时生成了错误。 转换将不会被执行。 当转换类的“Initialize()”失败或返回 false 时发生。 Initialize() 函数中的代码来自 #@template#< 指令和指令处理器中指定的>基转换类。 导致初始化失败的错误可能位于错误列表中。 调查失败的原因。 可以按照调试模板的过程查看 Initialize() 的实际生成代码。
程序集“{0}”对应的指令处理器“{1}”未被授予“FullTrust”权限集。 仅允许受信任的程序集提供指令处理器。 不会加载此指令处理器。 当系统不向包含指令处理器的程序集授予 FullTrust 权限时发生。 该消息提供程序集的名称和指令处理器的名称。 请确保仅在本地计算机上使用受信任的程序集。
路径“{0}”必须是此计算机的本地路径或属于您的受信任区域。 当指令或程序集指令引用不在本地计算机或网络信任区域中的文件时发生。 请确保指令或程序集指令所在的目录位于受信任的区域中。 可以通过 Internet Explorer 将网络目录添加到受信任的区域。
多个语法错误,例如“令牌'catch'无效”或“命名空间不能直接包含成员” 模板代码中的右大括号太多。 编译器将它与标准生成代码混淆。 检查代码分隔符内的右大括号和括号的数目。
循环或条件未正确编译或执行。 例如: <#if (i>10)#> Number is: <#= i #>

此代码始终输出 i 的值。 只有“数字为:”是有条件的。
在 C# 中,始终使用大括号包围嵌入在控件语句中的文本块。 添加大括号: <#if (i>10) { #> Number is: <#= i #><# } #>.
处理设计时模板或编译运行时(预处理)模板时,“表达式过于复杂”。

Visual Studio 在尝试检查运行时模板生成的代码时停止工作。
文本块太长。 T4 将文本块转换为字符串串联表达式,每个模板行都有一个字符串文本。 很长的文本块可以超过编译器的大小限制。 将长文本块分成表达块,例如:

<#= "" #>

警告说明和修复

下表列出了最常见的警告以及修复(如果可用)。

警告消息 Description 解决方案
加载 include 文件“{0}”返回 null 或空字符串。 如果包含的文本模板文件为空,则发生此事件。 该消息提供包含文件的文件名。 删除 include 指令或确保文件包含一些内容。
编译转换: 将此字符串追加到编译转换时源自编译器的所有错误或警告。 此字符串表示编译器引发错误或警告。 如果在查找 DLL 时遇到问题,则如果 DLL 位于 GAC 中,可能需要提供完整路径或完全限定的强名称。
指令中已存在参数“{0}”。 将忽略重复参数。 在指令中多次指定参数时发生。 该消息提供参数的名称和指令的行号。 删除重复的参数规范。
加载包含文件“”{0}时出错。 将忽略 include 指令。 在找不到指令中指定的 include 文件时发生。 该消息提供文件的名称和指令的行号。 请确保包含文件与原始文本模板文件位于同一目录中,或存在于向主机注册的包含目录中。
为 Transformation 类指定了无效的基类。 基类必须派生自 Microsoft.VisualStudio.TextTemplating.TextTransformation。 当模板指令中的inherits参数指定的类不继承自TextTransformation时会发生。 该消息提供模板指令的行号。 指定派生自 TextTransformation. 的类。
在“template”指令中指定了无效的区域设置。 文化必须采用“xx-XX”格式。 将使用不变文化设置。 当模板指令中的文化信息参数被错误指定时发生。 该消息提供模板指令的行号。 将文化代码参数更改为“xx-XX”格式的有效文化代码。
模板指令中指定了无效的调试值“{0}”。 调试值必须是“真”或“假”。 将使用默认值“false”。 模板指令中的参数 debug 被错误地指定时会发生。 该消息提供模板指令的行号。 将调试参数设置为“true”或“false”。
模板指令中指定了无效的 HostSpecific 值“{0}”。 HostSpecific 值必须是“true”或“false”。 将使用默认值“false”。 当指令中的 template 主机特定参数指定错误时发生。 该消息提供模板指令的行号。 将特定于主机的参数设置为“true”或“false”。
在“template”指令中指定了无效的语言“{0}”。 语言必须是“C#”或“VB”。 将使用默认值“C#”。 template 指令中指定不受支持的语言时发生。 仅允许使用“C#”或“VB”(不区分大小写)。 该消息提供模板指令的行号。 language 模板指令中的参数设置为“C#”或“VB”。
模板中发现了多个输出指令。 除了第一个,所有项都将被忽略。 在模板文件中指定多个 output 指令时发生。 该消息提供重复输出指令的行号。 删除重复 output 指令。
模板中发现了多个模板指令。 除了第一个,所有项都将被忽略。 应在一个模板指令中指定模板指令的多个参数。 如果在文本模板文件(包括包含的文件)中指定多个 template 指令,则会发生此情况。 该消息提供重复模板指令的行号。 将不同的 template 指令聚合为一个 template 指令。
未为名为“”{0}的指令指定处理器。 该指令将被忽略。 如果指定指令 custom ,但不提供 processor 属性,则会发生此事件。 该消息提供指令的名称和行号。 提供一个带有processor处理器名称directive的属性用于指令。
找不到名为“{0}”的处理器用于指令“{1}”。 该指令将被忽略。 当系统找不到您在 custom 指令中指定的 directive 处理器时,便会发生该问题。 该消息提供指令名称、处理器名称和指令的行号。 processor 指令中的属性设置为指令处理器的名称。
找不到指令“{1}”所需的必需参数“{0}”。 该指令将被忽略。 当系统不提供必需的指令参数时发生。 该消息提供缺少的参数、指令名称和行号的名称。 提供缺少的参数。
名为“{0}”的处理器不支持名为“”{1}的指令。 该指令将被忽略。 当指令处理器不支持指令时发生。 该消息提供有问题的指令的名称和行号以及指令处理器的名称。 更正指令的名称。
文件“{0}”的 include 指令会导致无限循环。 如果指定了循环包含指令(例如,文件 A 包含文件 B,然后文件 B 又包含文件 A),则显示。 不要指定循环包含指令。
正在执行转换: 将此字符串前置到运行转换时生成的所有错误或警告中。 不適用。
在块中发现了意外的开始或结束标记。 请确保没有错误地键入开始或结束标记,并且模板中没有任何嵌套块。 当遇到意外的<#或#>时显示。 也就是说,如果你在另一个未关闭的起始标签之后有一个<#,或者在它前面不存在未关闭的起始标签时,你有一个#>。 该消息提供不匹配标记的行号信息。 删除不匹配的开始或结束标记,或使用转义字符。
指令以错误格式指定。 该指令将被忽略。 请指定指令格式为<#@ name [parametername="parametervalue"]* #> 如果指令未以正确的格式指定,则由分析器显示。 该消息提供错误指令的行号。 请确保所有指令都采用格式 <#@ name [parametername="parametervalue"]* #>。 有关详细信息,请参阅 T4 文本模板指令
无法加载用于已注册指令处理器“{1}”的程序集“{0}”。

{2}
当主机无法加载指令处理器时发生。 该消息标识为指令处理器提供的程序集和指令处理器的名称。 请确保正确注册指令处理器,并且程序集存在。
在程序集“{1}”中找不到类型“{0}”以处理已注册的指令处理器“{2}”。

{3}
当无法从其程序集加载指令处理器类型时发生。 该消息提供类型、程序集和指令处理器的名称。 vshost 在注册表中查找指令处理器信息(名称、程序集和类型)。 请确保正确注册指令处理器,并且该类型存在于程序集中。
加载程序集“{0}”时出现问题 加载程序集时发生问题。 该消息提供程序集的名称。 可以指定程序集,以在<@#assembly#>指令和指令处理器中加载。 此字符串后面的错误消息应提供有关程序集加载失败的原因的更多数据。
为名为“”{1}的指令创建和初始化处理器时出现问题。 处理器的类型为 {0}. 该指令将被忽略。 当系统无法创建或初始化指令处理器时发生。 该消息提供指令的名称和行号以及处理器的类型。 请确保使用正确的指令处理器,并且指令处理器具有公共默认构造函数。 否则,请使用调试选项找出指令处理器的 Initialize() 方法失败的原因。 有关详细信息,请参阅 文本模板疑难解答
处理名为“'”{0}的指令时引发了异常。 当指令处理器在处理指令时引发异常时发生。 请确保指令处理器的参数正确。
主机在尝试解析程序集引用“”{0}时引发异常。 当主机尝试解析程序集引用时引发异常时发生。 该消息提供程序集引用字符串。 程序集引用来自 <@#assembly#> 指令和指令处理器。 请确保程序集参数中提供的“name”参数正确。
尝试为指令 {2} 指定不受支持的 {1} 值“{0}”, 当您提供不受支持的 requires 或 provides 参数时,由 RequiresProvidesDirectiveProcessor 触发该情况(我们生成的所有指令处理器均派生自此处理器)。 确保在 requires 和 provides 参数中提供的 name='value' 对的名称正确无误。