1. 问题描述
A程序集引用了 Newtonsoft.Json 6.0程序集
B程序集引用了 Newtonsoft.Json 12.0程序集
此时A引用B,就会报:发现同一依赖程序集的不同版本间存在无法解决的冲突 这一警告,执行程序就会报错–System.IO.FileNotFoundException: 未能加载文件或程序集Newtonsoft.Json xx.x的错误
A:引用Newtonsoft.Json 6.0
FuncA()
{
var obj= Newtonsoft.Json.Obj;
B.FuncB();
}
B: 引用Newtonsoft.Json 12.0
FuncB()
{
return Newtonsoft.Json.Obj;
}
2. 原因分析
这是因为依赖顺序引起的。A引用了B,首先会先生成B,而B引用了 Newtonsoft.Json 12.0,那么VS就会将源引用文件(Newtonsoft.Json 12.0)复制到B程序集同一目录(bin/Debug)下,名为Newtonsoft.Json.dll文件,其内嵌程序集版本为12.0。
然后A引用了B,所以会将B程序集和B程序集的依赖项12.0(Newtonsoft.Json.dll)给复制到A的程序集目录下,而A又引用了Newtonsoft.Json 6.0程序集文件,所以又将6.0的dll文件给复制到自己程序集目录下。因为两个Newtonsoft.Json.dll重名,所以直接覆盖了前者,那么只保留了Newtonsoft.Json 6.0。
当我们调用Func方法中的B.FuncB()时候,CLR会搜索B程序集,找到后再调用 return Newtonsoft.Json.Obj 这行代码,而这行代码又用到了Newtonsoft.Json程序集,接下来CLR搜索Newtonsoft.Json.dll,文件名称满足,接下来CLR判断其标识,发现版本号是6.0,与B程序集清单里注册的12.0版本不符,故而才会报出异常:未能加载文件或程序集Newtonsoft.Json 12.0。
3 解决方案
以下方案所修改的为程序的配置文件 App.config 或 Web.config文件
方案1. 通过bindingRedirect节点重定向,即当找到6.0的版本时,给定向到12.0版本
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
方案2. 对每个版本指定codeBase路径,然后分别放上不同版本的程序集,这样就可以加载两个相同的程序集
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json"
publicKeyToken="30ad4fe6b2a6aeed"
culture="neutral" />
<codeBase version="6.0.0.0"
href="F:\6.0\Newtonsoft.Json.dll" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json"
publicKeyToken="30ad4fe6b2a6aeed"
culture="neutral" />
<codeBase version="12.0.0.0"
href="F:\12.0\Newtonsoft.Json.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>