在.NET 6的T4模板中使用DisplayAttribute编译报错,如何解决?
在.NET 6 T4模板中读取DisplayAttribute的报错解决
问题场景
在.NET 6项目(Visual Studio 2022 17.0.4版本)的自定义T4模板中,尝试读取枚举成员的DisplayAttribute时,编译模板出现类型找不到的错误,提示该类型已转发到旧版本的程序集。
原T4代码片段
<#@ template debug="true" hostspecific="true" language="C#" compilerOptions="/langversion:10" #> <#@ assembly name="System" #> <#@ assembly name="System.Runtime" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.ComponentModel.Annotations" #> <#@ import namespace="System" #> <#@ import namespace="System.Reflection" #> <#@ import namespace="System.Runtime" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.ComponentModel.DataAnnotations" #> <#@ output extension=".cs" #> <# static string GetEnumValueDisplayName(Enum value) { Type type = value.GetType(); MemberInfo[] memInfo = type.GetMember(value.ToString()); DisplayAttribute? dispalyAttribute = null; if (memInfo != null && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false); if (attrs != null && attrs.Length > 0) dispalyAttribute = attrs[0] as DisplayAttribute; } return dispalyAttribute?.Name ?? ""; } #> <# foreach(myEnum en in Enum.GetValues(typeof(MyEnum))) {#> public static class <#=@en.ToString()#> { public const string Value = "<#=@en.ToString()#>";public const string Text = "<#=@GetEnumValueDisplayName(en)#>";} <#}#>
报错信息
Compiling transformation: The type name 'DisplayAttribute' could not be found in the namespace 'System.ComponentModel.DataAnnotations'. This type has been forwarded to assembly 'System.ComponentModel.Annotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' Consider adding a reference to that assembly.
解决方案
1. 指定正确的程序集强名称引用
.NET 6中System.ComponentModel.Annotations的强名称版本为6.0.0.0,替换原有的程序集引用语句:
// 替换原有的<#@ assembly name="System.ComponentModel.Annotations" #> <#@ assembly name="System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" #>
2. 使用项目本地NuGet包路径引用(可选)
如果项目已安装该NuGet包,可直接引用本地包中的程序集路径(注意替换版本号为你项目中使用的版本):
<#@ assembly name="$(SolutionDir)packages\System.ComponentModel.Annotations.6.0.0\lib\net6.0\System.ComponentModel.Annotations.dll" #>
3. 优化获取DisplayAttribute的方法
可以用LINQ简化原方法,同时避免空引用检查的冗余代码:
static string GetEnumValueDisplayName(Enum value) { return value.GetType() .GetMember(value.ToString()) .FirstOrDefault()? .GetCustomAttribute<DisplayAttribute>()? .Name ?? string.Empty; }
注意事项
- 确保项目中已安装
System.ComponentModel.AnnotationsNuGet包(.NET 6控制台/类库项目可能需要手动安装)。 - 若使用强名称引用,需保证版本号与项目依赖的版本完全一致。
- 修改T4模板后,可尝试重启Visual Studio或重新生成项目,确保模板编译生效。
内容的提问来源于stack exchange,提问作者theGhostN
相关产品推荐
相关产品推荐

