VS2022扩展开发:如何解决T4模板运行时EnvDTE与Microsoft.VisualStudio.Interop类型冲突
问题解决方案
核心原因
VS2022 17.x版本开始将传统EnvDTE系列互操作程序集的类型全部嵌入到了Microsoft.VisualStudio.Interop.dll中,T4模板运行时会默认加载新旧两套程序集,导致同名类型冲突。
可行解决思路
优先级建议
优先尝试方案1,无需修改业务代码,配置成本最低;如果方案1不生效再依次尝试后续方案。
- 方案1:在T4模板顶部添加程序集排除指令
直接在你的.tt文件最开头加入以下指令,手动排除旧版本EnvDTE程序集的引用,让T4编译时只使用Microsoft.VisualStudio.Interop里的类型:
<#@ assembly name="!EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #>
如果还有EnvDTE80、EnvDTE90等相关旧程序集冲突,也可以按照相同格式加对应的排除指令,!前缀就是T4模板原生支持的排除引用语法。
- 方案2:显式指定类型的命名空间别名
如果排除程序集后出现类型找不到的报错,可以在T4的代码块顶部加extern alias声明,然后用别名限定类型:
首先在T4模板中添加指定别名的程序集引用:
<#@ assembly name="Microsoft.VisualStudio.Interop, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" alias="VSInterop" #>
然后在代码块中声明类型别名:
<#+ extern alias VSInterop; using DTE = VSInterop::EnvDTE.DTE; using Project = VSInterop::EnvDTE.Project; using ProjectItem = VSInterop::EnvDTE.ProjectItem; // 其他需要用到的冲突类型都可以按照这个格式统一指定别名 #>
所有冲突类型都统一指定为Microsoft.VisualStudio.Interop下的实现,即可完成消歧义。
- 方案3:调整DslPackage项目的绑定重定向配置
在你的DslPackage项目的app.config文件中添加EnvDTE的绑定重定向,强制所有对EnvDTE 8.0版本的请求都转发到Microsoft.VisualStudio.Interop中嵌入的实现:
<dependentAssembly> <assemblyIdentity name="EnvDTE" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-17.0.0.0" newVersion="17.0.0.0" /> </dependentAssembly>
同时移除项目中所有显式的EnvDTE相关NuGet包或者程序集引用,依赖VS2022运行时自带的Microsoft.VisualStudio.Interop即可。
- 方案4:修改T4模板的宿主配置
如果是DSL自定义的T4宿主,可在宿主实现的ResolveAssemblyReference方法中过滤掉EnvDTE 8.0.0.0版本的程序集返回,只返回Microsoft.VisualStudio.Interop的路径,从根源上避免冲突程序集被加载。
内容的提问来源于stack exchange,提问作者Michael Sawczyn
相关产品推荐
相关产品推荐

