VB.NET使用T4运行时模板报错:ReportTemplate等类未定义
T4运行时文本模板生成报表报错排查
问题概述
使用T4 Run-time Text Templates向HTML模板传递数据生成报表时,出现三个错误:
A namespace cannot directly contain members such as fields or methods'ReportTemplate' is not defined- T4模板中提示
Type 'Global.Sample.ReportModel' is not defined
原代码片段
Form1代码
Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim rpt = New ReportTemplate() rpt.Session = New Dictionary(Of String, Object)() rpt.Session("Model") = New ReportModel With { .CustomerName = "TEST", .Date = DateTime.Now, .OrderItems = New List(Of OrderItem)() From { New OrderItem() With { .Name = "Product 1", .Price = 100, .Count = 2 }, New OrderItem() With { .Name = "Product 2", .Price = 200, .Count = 3 }, New OrderItem() With { .Name = "Product 3", .Price = 50, .Count = 1 } } } rpt.Initialize() Me.WebBrowser1.DocumentText = rpt.TransformText() End Sub End Class
模型代码
Public Class ReportModel Public Property CustomerName() As String Public Property [Date]() As DateTime Public Property OrderItems() As List(Of OrderItem) End Class Public Class OrderItem Public Property Name() As String Public Property Price() As Integer Public Property Count() As Integer End Class
ReportTemplate.tt代码
<#@ template language="VB" #> 'error below line code Type 'Global.Sample.ReportModel' is not defined <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ parameter name="Model" type="ReportModel"#> <html> <head> <title></title> <style type="text/css"> body { font-family: Calibri;width:400px;} table { text-align:center; } .container {width:400px; height:100%;} </style> </head> <body> <div class="container"> <h1 style="text-align:center;">Order</h1> <hr/> <table style="width:100%"> <tr> <td>Customer: <#=Model.CustomerName#></td> <td>Order Date: <#=Model.Date#></td> </tr> </table> <hr/> <table style="width:100%"> <tr><th>Index</th><th>Name</th><th>Price</th><th>Count</th><th>Sum</th></tr> <# Dim index As Integer =1 For Each item In Model.OrderItems #> <tr> <td><#=index#></td> <td><#=item.Name#></td> <td><#=item.Price#></td> <td><#=item.Count#></td> <td><#=item.Count * item.Price#></td> </tr> <# index += 1 Next Dim total= Model.OrderItems.Sum(Function(x) x.Count * x.Price) #> <tr><td></td><td></td><td></td><th>Total:</th><th><#=total#></th></tr> </table> <div> </body> </html>
错误原因及修复方案
1. A namespace cannot directly contain members such as fields or methods
原因:模型类直接暴露在根命名空间下,同时T4模板中使用了VB单行注释('),该注释会被当作生成代码的一部分,导致语法结构异常。
修复:
- 给模型类添加明确的命名空间;
- 改用T4标准注释格式
<#-- 注释内容 -->替换原单行注释。
2. 'ReportTemplate' is not defined
原因:T4模板未配置正确的自定义工具,无法生成对应的模板类。
修复:
- 右键
ReportTemplate.tt文件 → 属性 → 自定义工具 → 设置为TextTemplatingFileGenerator; - 保存模板文件,触发代码生成,此时会在模板文件下方生成
ReportTemplate.vb文件。
3. Type 'Global.Sample.ReportModel' is not defined
原因:T4模板未引用包含模型类的程序集,也未导入模型所在的命名空间。
修复:
- 在T4模板中添加
<#@ assembly name="$(TargetPath)" #>,引用当前项目生成的程序集; - 添加
<#@ import namespace="Sample" #>(对应模型类的命名空间),导入模型所在命名空间。
修正后的完整代码
模型代码(添加命名空间)
Namespace Sample Public Class ReportModel Public Property CustomerName() As String Public Property [Date]() As DateTime Public Property OrderItems() As List(Of OrderItem) End Class Public Class OrderItem Public Property Name() As String Public Property Price() As Integer Public Property Count() As Integer End Class End Namespace
ReportTemplate.tt代码(修复注释、添加引用和命名空间)
<#@ template language="VB" #> <#-- 修正注释格式 --> <#@ assembly name="System.Core" #> <#@ assembly name="$(TargetPath)" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="Sample" #> <#@ parameter name="Model" type="ReportModel"#> <html> <head> <title></title> <style type="text/css"> body { font-family: Calibri;width:400px;} table { text-align:center; } .container {width:400px; height:100%;} </style> </head> <body> <div class="container"> <h1 style="text-align:center;">Order</h1> <hr/> <table style="width:100%"> <tr> <td>Customer: <#=Model.CustomerName#></td> <td>Order Date: <#=Model.Date.ToString("yyyy-MM-dd HH:mm:ss")#></td> </tr> </table> <hr/> <table style="width:100%"> <tr><th>Index</th><th>Name</th><th>Price</th><th>Count</th><th>Sum</th></tr> <# Dim index As Integer =1 For Each item In Model.OrderItems #> <tr> <td><#=index#></td> <td><#=item.Name#></td> <td><#=item.Price#></td> <td><#=item.Count#></td> <td><#=item.Count * item.Price#></td> </tr> <# index += 1 Next Dim total= Model.OrderItems.Sum(Function(x) x.Count * x.Price) #> <tr><td></td><td></td><td></td><th>Total:</th><th><#=total#></th></tr> </table> </div> </body> </html>
Form1代码(添加命名空间引用)
Imports Sample Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim rpt = New ReportTemplate() rpt.Session = New Dictionary(Of String, Object)() rpt.Session("Model") = New ReportModel With { .CustomerName = "TEST", .Date = DateTime.Now, .OrderItems = New List(Of OrderItem)() From { New OrderItem() With { .Name = "Product 1", .Price = 100, .Count = 2 }, New OrderItem() With { .Name = "Product 2", .Price = 200, .Count = 3 }, New OrderItem() With { .Name = "Product 3", .Price = 50, .Count = 1 } } } rpt.Initialize() Me.WebBrowser1.DocumentText = rpt.TransformText() End Sub End Class
内容的提问来源于stack exchange,提问作者roy
相关产品推荐
相关产品推荐

