Newtonsoft Json.NET版本不兼容(DLL地狱)

Newtonsoft Json.NET版本不兼容(DLL地狱),.net,json.net,versioning,.net-assembly,global-assembly-cache,.net,Json.net,Versioning,.net Assembly,Global Assembly Cache,Json发布具有相同强名称的不兼容版本,仅更改文件版本 根据: 具有相同强名称的程序集应相同 因此,如果我们无法控制的其他应用程序将不同版本的Newtonsoft.Json.dll放入GAC,我们的应用程序就会中断 有没有办法强制.NET加载我们需要的特定版本 更新: 让我更深入地解释这个问题: 据我所知,在.NET中,在CLR尝试解析程序集并失败之前,没有解析程序集的机制 只有AppDomain.AssemblyResolve事件,它仅在程序集未解析时激发。通常这就足够了 但是在使用Newto

Json发布具有相同强名称的不兼容版本,仅更改文件版本

根据:

具有相同强名称的程序集应相同

因此,如果我们无法控制的其他应用程序将不同版本的Newtonsoft.Json.dll放入GAC,我们的应用程序就会中断

有没有办法强制.NET加载我们需要的特定版本

更新:

让我更深入地解释这个问题:

据我所知,在.NET中,在CLR尝试解析程序集并失败之前,没有解析程序集的机制

只有AppDomain.AssemblyResolve事件,它仅在程序集未解析时激发。通常这就足够了

但是在使用Newtonsoft.Json的情况下,它不会无法解析程序集,但它只是加载了错误的程序集

这是因为Newtonsoft.Json发布了具有相同强名称的不兼容版本

示例:

假设我们的应用程序是根据N.J.dll编译的(汇编版本1.0,文件版本1.0)

然后,将同一dll的其他不兼容版本放入GAC N.J.dll(程序集版本1.0,文件版本1.1

因为它们只更改文件版本而不更改程序集版本,所以这两个程序集具有相同的强名称。

因此,对于试图解析N.J.dll(汇编版本1.0)的应用程序.NET,它会在GAC中看到dll并加载它。(因为.NET总是喜欢GAC中的程序集用于“bin”文件夹中的程序集

但加载的程序集是错误的。它的文件版本为1.1,与版本1.0不兼容

由于两个程序集具有相同的程序集版本,.NET看不到它们之间有任何差异。但当它实际尝试解析内部的某个类或成员时,它失败了,因为它在版本1.1中被更改了

整个应用程序将失败并出现不可预测的错误。

最糟糕的是,即使我的应用程序没有将newtonsoft.json.dll放入GAC,我无法控制的其他应用程序也会将不同版本的newtonsoft.json.dll放入GAC—我的应用程序将因不可预知的异常而崩溃

所以我的问题是,在.NET加载错误的程序集之前,我可以先加载正确的程序集吗

更新


此问题的问题以注释结束,该注释表明Newtonsoft.Json的作者不了解.NET版本控制以及这一点的重要性。

程序集加载器将只探测缺少的程序集,即尚未加载的程序集。如果将DLL部署到应用程序安装文件夹,然后在应用程序启动时显式加载它,则程序集加载程序将不会再次尝试从GAC加载它

您可以使用
assembly.LoadFrom
方法显式加载程序集


有关更多信息,请参阅。

在-J#在程序集版本未更改的情况下被重新删除之前,甚至在Microsoft上也发生过这种情况。若您在安装过程中检测到它,您可以要求用户在GAC中安装正确版本的程序集。另一种选择是从相同的源生成自己的二进制文件,并根据您的意愿为其指定强名称(如果许可证允许),问题更大。微软本身在其库和SDK中使用Newtonsoft Json.NET。因此,任何使用它们的东西都可能在任何时候出现异常错误。这最终解释了半年前我在MVCWebAPI应用程序中收到的一系列意外异常。该应用程序使用的Json.Net版本高于与WebAPI本身捆绑的版本。应用程序在部署后立即工作正常,直到IIS决定暂停它(大约30分钟后停止使用)。当有人在挂起后访问应用程序时,IIS会尝试再次启动它,但不知怎么搞砸了Json.Net版本,我的工作应用程序因此臭名昭著地死掉。我在GAC中没有Json.Net,只使用NuGet来管理我的依赖项。newtonsoft不随AssemblyFileVersion一起更新AssemblyVersion是正确的。通常,他们的文件或产品版本与其软件包版本相匹配。文件和产品版本都是win32概念。因此,对于包6.0.4和6.0.8,例如,它们使用相同的汇编版本,我相信,它们也确保了完全的向后/向前兼容。唯一的更改必须是bug修复。因此,在理想情况下,这不应该破坏您的应用程序。但我同意他们不应该这样做。是的,但这很难实现。因为它需要在使用给定程序集的任何类型初始化之前发生。它需要很早,我不知道任何事件或入口点,可靠地发生在早期,它是什么类型的应用程序?这是一个网站,控制台应用程序。。。几乎总是有一个启动的地方,你可以把这些代码放在那里,但具体放在哪里取决于应用程序的类型。你也可以创建一个加载器应用程序。加载器应用程序将创建一个新的应用程序域,在调用应用程序的入口点运行应用程序之前,将应用程序的DLL显式加载到新的应用程序域中。这是我能想象到的最极端的解决方案,对于您的情况几乎肯定没有必要。另一种选择是动态绑定到Newtonsoft程序集,而不是创建静态绑定。这将涉及按名称加载类型,并使用反射查找构造函数和要调用的方法。只有在应用程序中的少数位置使用Newtonsoft时,这种方法才实用。LoadFrom()和LoadFile()不一定从文件加载请求的程序集。如果具有其标识的程序集位于GAC中,则将使用GAC副本。