Infragistics 13.1 升级至 15.2 后出现编译错误
结论
这是程序集版本混用导致的错误。Shell.xaml.cs 传入的 XamDockManager 来自 InfragisticsWPF4.DockManager.v15.2.dll,而 IXamDockManagerInstance.setXamDockManagerInstance(...) 的参数类型仍指向 InfragisticsWPF4.DockManager.v13.1.dll。
虽然两个类型的命名空间和类名完全相同,但它们来自不同的强名称程序集,CLR 和 C# 编译器会将其视为不同类型,强制转换也无法解决。
整个解决方案及其依赖程序集需要统一引用 15.2。先检查定义 IXamDockManagerInstance 的项目或 DLL,它很可能仍是用 13.1 编译的。
为什么会出现看似矛盾的类型转换错误
错误信息中的两种类型表面上都是:
Infragistics.Windows.DockManager.XamDockManager
它们实际对应不同的程序集身份:
InfragisticsWPF4.DockManager.v13.1
InfragisticsWPF4.DockManager.v15.2
.NET 类型身份由命名空间、类型名及定义该类型的程序集共同决定。这里的两个类型可以理解为:
XamDockManager from InfragisticsWPF4.DockManager.v13.1.dll
XamDockManager from InfragisticsWPF4.DockManager.v15.2.dll
错误 6 已经指出,当前调用涉及的某个接口或程序集仍要求:
InfragisticsWPF4.DockManager.v13.1,
Version=13.1.20131.1009,
PublicKeyToken=7dd5c3163f2cd0cb
因此,计算机上安装了哪些 Infragistics 版本不会直接决定编译结果。编译时使用的是项目文件中的引用,以及已编译 DLL 元数据中记录的依赖关系。
先检查 IXamDockManagerInstance 的定义
检查范围不要局限于 Shell.xaml.cs,还要找到以下接口的定义:
Prism.Modules.Common.IXamDockManagerInstance
它可能类似于:
public interface IXamDockManagerInstance
{
void setXamDockManagerInstance(
Infragistics.Windows.DockManager.XamDockManager dockManager);
}
如果 Prism.Modules.Common 是当前解决方案中的项目,请检查它引用的 InfragisticsWPF4.DockManager 版本。
如果它是预编译 DLL,可以用 ILSpy、dotPeek、Visual Studio 对象浏览器或 ildasm 查看程序集引用。发现其中仍引用 InfragisticsWPF4.DockManager.v13.1 时,需要找到源项目并使用 15.2 重新编译。只替换应用程序项目中的 Infragistics 引用无法消除这个依赖。
搜索解决方案中的旧版本引用
关闭 Visual Studio 后,在解决方案目录中搜索:
InfragisticsWPF4.DockManager.v13.1
InfragisticsWPF4
13.1.20131.1009
Infragistics\2013.1
PowerShell 搜索命令如下:
Get-ChildItem -Recurse -File |
Select-String -Pattern 'InfragisticsWPF4.*v13\.1|13\.1\.20131\.1009|Infragistics\\2013\.1'
重点检查以下文件:
*.csproj
*.vbproj
*.xaml
app.config
packages.config
licenses.licx
项目文件中的旧引用通常类似:
<Reference Include="InfragisticsWPF4.DockManager.v13.1">
<HintPath>..\lib\InfragisticsWPF4.DockManager.v13.1.dll</HintPath>
</Reference>
删除旧引用,再通过 Visual Studio 添加对应的 15.2 DLL。更新后的项目文件应指向 15.2,例如:
<Reference Include="InfragisticsWPF4.DockManager.v15.2">
<HintPath>C:\Program Files (x86)\Infragistics\2015.2\WPF\CLR4.0\Bin\InfragisticsWPF4.DockManager.v15.2.dll</HintPath>
<Private>True</Private>
</Reference>
具体路径以本机安装位置或项目统一使用的第三方库目录为准,不要直接照搬示例路径。
检查项目引用是否退化成了 DLL 引用
大型解决方案中常见这样的组合:
Prism.ApplicationHost引用 15.2;Prism.Modules.Common仍引用 13.1;- 主项目引用的是旧版
Prism.Modules.Common.dll,没有直接引用Prism.Modules.Common项目。
在 Visual Studio 的“引用”或“依赖项”中检查 Prism.Modules.Common:
- 源项目已包含在当前解决方案中时,优先使用项目引用。
- 如果引用指向某个
bin\Debug、bin\Release或公共输出目录中的 DLL,确认它是否为升级前遗留的二进制文件。 - 必须使用 DLL 时,其提供方需要先完成 15.2 升级并重新编译。
项目引用通常应类似:
<ProjectReference Include="..\Prism.Modules.Common\Prism.Modules.Common.csproj">
<Project>{PROJECT-GUID}</Project>
<Name>Prism.Modules.Common</Name>
</ProjectReference>
不要继续引用旧输出:
<Reference Include="Prism.Modules.Common">
<HintPath>..\SomeOldOutput\Prism.Modules.Common.dll</HintPath>
</Reference>
按依赖顺序重新编译
迁移时从依赖链底部开始:
- 找出所有直接引用 Infragistics 的基础类库。
- 将这些类库统一升级到 15.2。
- 编译基础类库。
- 编译引用这些类库的 Prism 模块。
- 最后编译应用程序宿主项目。
针对当前错误,优先处理以下依赖关系:
Prism.Modules.Common
↓
Prism.ApplicationHost
如果 Prism.Modules.Common 的公共接口使用了 XamDockManager,调用方在编译时也必须解析到定义该参数类型的同一版本程序集。
清除旧的构建产物
修改引用后,关闭 Visual Studio,删除各项目中的以下目录:
bin
obj
同时检查解决方案是否使用了公共输出目录。例如:
<OutputPath>..\..\Build\Bin\</OutputPath>
如果存在这类配置,还要清理公共输出目录中的旧 DLL。无法确认用途的文件不要删除。
重新打开解决方案后执行:
Clean Solution
Rebuild Solution
如果 Visual Studio 仍显示旧引用,请删除该引用并重新添加。单独修改引用属性可能无法解决问题。
检查最终加载和复制的 DLL
编译前后都应检查输出目录,确认其中没有同时混入:
InfragisticsWPF4.DockManager.v13.1.dll
InfragisticsWPF4.DockManager.v15.2.dll
迁移完成后,应用程序输出目录通常不应同时存在这两个版本。还要检查各引用的 Path 属性,避免 Visual Studio 中显示的是 15.2,实际复制的 DLL 却来自旧的共享目录。
需要进一步排查时,可以使用 MSBuild 诊断日志追踪引用解析过程:
msbuild YourSolution.sln /t:Rebuild /v:diag > msbuild.log
然后在 msbuild.log 中搜索:
InfragisticsWPF4.DockManager
v13.1
13.1.20131.1009
日志通常会显示哪个项目请求了旧程序集,以及 MSBuild 最终从哪个路径解析该程序集。
不要用强制类型转换处理
下面的修改无法解决问题:
instance.setXamDockManagerInstance(
(Infragistics.Windows.DockManager.XamDockManager)dockManager);
编译器看到的源类型和目标类型来自两个不同的程序集,两者之间没有继承关系,也不存在合法的引用转换。使用反射、dynamic 或序列化绕过同样不合适,只会掩盖依赖版本尚未统一的问题。
应当重新编译接口及其实现,让方法参数和调用方使用同一个 15.2 类型。
Binding Redirect 通常不适用于这个错误
app.config 中的程序集绑定重定向主要影响运行时程序集加载。当前问题发生在编译期,而且 Infragistics 的程序集名称带有版本后缀:
InfragisticsWPF4.DockManager.v13.1
InfragisticsWPF4.DockManager.v15.2
这通常表示它们是名称不同的程序集,并非同名程序集使用了不同的 AssemblyVersion。绑定重定向无法代替旧类库的重新编译。
只有当程序集名称相同、厂商明确支持重定向,而且错误发生在运行时加载阶段,才适合考虑 binding redirect。当前错误不足以支持这种处理方式。
建议的处理顺序
按以下顺序排查:
- 定位
IXamDockManagerInstance定义所在的项目或 DLL。 - 检查该项目或 DLL 是否依赖
InfragisticsWPF4.DockManager.v13.1。 - 搜索整个解决方案中的
v13.1、旧HintPath和旧版本号。 - 将所有直接依赖 Infragistics 的项目统一升级到 15.2。
- 将可以使用项目引用的旧 DLL 引用改为项目引用。
- 清理所有
bin、obj以及公共输出目录中的旧构建产物。 - 从基础类库开始,按依赖顺序重新编译。
- 使用 MSBuild 诊断日志定位仍在请求 13.1 的项目。
卸载 Infragistics 13.1 不会修改项目文件或 DLL 元数据中已经写入的引用。整条项目依赖链都使用 15.2 重新编译后,迁移才能完成。
备注:内容仅供参考。
