最近在项目上使用 Ozeki SDK 的时候遇到版本冲突的问题,冲突库是 Newtonsoft.Json ,主要因为 Ozeki SDK 把 Newtonsoft.Json 1.0.x 嵌入了,而我的项目里引用的是 Newtonsoft.Json 11.0.2 ,在使用相关对象时编译器报错:
The type 'JsonConvert' exists in both 'XXX.XXX, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=...' and 'Newtonsoft.Json, Version
=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'
然后 Baidu 了下,搜到的解决办法竟然是在 App.config 中添加类似以下一段代码
<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="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>鄙人试了一下,尝试改了改 publicKeyToken,又尝试改了改 oldVersion,又尝试改了改 newVersion,还是不管用。这段什么意思呢?读者有心可以查阅官方文档 assemblyBinding MSDN。
总之,是复杂复杂滴!!我们遇到的是什么问题呢,是同一个DLL不同版本互相冲突?还是程序集版本需要重定向?
实际我看了下官方文档,因为没代码例子,也不知这种重定向主要是解决什么问题的,读书的时候没学过,老师也没教过啊... ...但是不打紧,接下来就该打脸了。
这归根结底是命名空间冲突,晴树SEU 的《命名空间namespace ,以及重复定义的问题解析》 提到:
名字空间是用来划分冲突域的,把全局名字空间划分成几个小的名字空间。全局函数,全局变量,
以及类的名字是在同一个全局名字空间中,有时为了防止命名冲突,会把这些名字放到不同的名
字空间中去。重定向学校老师没教过,命名空间的使用总教过吧,全局命名空间啊,你把它...把它...交还给老师啦??!!!
比方说,我们现在有个项目A 引用了 Newtonsoft.Json 最新版,然后项目A 需要引用项目B ,但是项目B 中有如下代码(具体来讲是命名空间)导致项目A 与原本正在使用的 Newtonsoft.Json 库的相关命名空间冲突:
using System;
namespace Newtonsoft.Json
{
public class JsonConvert
{
public string SerializeObject(object value)
{
throw new NotImplementedException();
}
}
}解决办法其实很简单,把后来者(程序集)加别名,用全局命名空间就可以区分开这些相同的命名空间,就不会影响项目对之前库的引用。
具体操作如下:
1、给后来者程序集加别名。

2、使用 extern alias 关键字来引用项目B 中的相关对象。
extern alias LibX;
using Newtonsoft.Json;
namespace DemoLibConflict.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var emp = new Employee { Name = "Tom" };
//假设这是项目正在使用 Newtonsoft.Json 库的代码。
string json = JsonConvert.SerializeObject(emp);
//假设这行是新增引用项目B 后使用的代码。
string json2 = LibX::Newtonsoft.Json.JsonConvert.SerializeObject(emp);
}
}
public class Employee
{
public string Name { get; set; }
}
}
这样就可以避免与其他命名空间冲突。

参考资料: