为什么该项目需要程序集绑定重定向?

时间:2019-04-10 18:01:17

标签: c# json.net nuget assembly-binding-redirect

我使用https://icanhasdot.net分析了我正在尝试的示例项目的NuGet依赖项。结果如下: enter image description here

该图未显示特定版本,但是我针对该项目使用.NET Framework 4.5,并且基于Visual Studio中的“ Manage Nuget”视图,我知道所有NuGet程序包(即,所有绿色方框)该图)在我的项目中需要Newtonsoft.Json > = 6.0.8,例如:

enter image description here

我想在我的项目中使用Newtonsoft.Json的较新版本,所以我添加了8.0.2版。因为这肯定是> = 6.0.8,所以我不希望这会引起问题。但是,当我运行该程序时,我立即收到一个System.IO异常消息,提示未找到Newtonsoft.Json 6。

我通过将带有程序集绑定重定向(Assembly Binding redirect: How and Why?)的app.config文件添加到较新版本的Newtonsoft.Json来解决了此问题,并解决了该问题。但是,我不明白,如果我的项目所依赖的所有NuGet包都要求require> = 6.0.8,那么为什么需要这样的绑定?8.0.2肯定是。

1 个答案:

答案 0 :(得分:2)

.NET运行时的概念称为强命名。

我可能会弄错很多技术细节,但是基本上一个没有有效命名的程序集基本上都说“我的名字是zivkan.utilities.dll”,而当另一个程序集针对我的程序集进行编译时,引用将显示为“我需要来自zivkan.utilities.thing的名为zivkan.utilities.dll的类。因此,它对版本一无所知,您可以放入任何包含zivkan.utilities.dll类的zivkan.utlities.thing,运行时将尝试运行它。

如果我使用强记号zivkan.utilities.dll,则该汇编程序将自己广告为“我的名字是zivkan.utilites.dll版本1.0.0,带有公钥...”(我要离开公钥剩下的我的答案)。现在,当针对另一个程序集进行编译时,编译后的引用将显示“我需要zivkan.utilities.dll 1.0.0版”。现在,当执行此命令时,.NET运行时将仅加载zivkan.utilities.dll版本1.0.0,如果版本不同,则失败,就像您看到的那样,您会得到一个错误。该程序可以具有绑定重定向,以告诉.NET运行时程序集加载器,当它看到在0.0.0.0和2.0.0.0版本之间对zivkan.utilties的请求以使用2.0.0.0版本时,这就是您解决的方法你的问题。

NuGet版本和程序集版本是两个独立的概念,但是由于它们通常是相同的值(或非常相似的值),因此并不是众所周知的区别。程序集版本是运行时事物,而NuGet软件包版本是构建时事物。

因此,想象一下没有绑定重定向的情况。您的程序CommandLineKeyVaultClient已加载,并且依赖于Newtonsoft.Json版本8.0.2。 .NET运行时将加载Newtonsoft.Json.dll并确认它确实是版本8.0.2。然后,.NET运行时看到CommandLineKeyVaultClient也依赖于Microsoft.Rest.ClientRuntime.dll,比如说版本1.0.0.0。因此,.NET运行时将加载该dll并确认程序集版本号。 Microsoft.Rest.ClientRuntime.dll依赖于Newtonsoft.Json.dll版本6.0.8。 .NET运行时看到Newtonsoft.Json版本8.0.2已经加载,但是该版本不匹配并且没有绑定重定向,因此让我们尝试将Newtonsoft.Json.dll加载到磁盘上(实际上是一个钩子,可以用来告诉加载器从其他目录加载dll,当您确实需要加载同一程序集的不同版本时,可以)。尝试时,它会看到程序集的版本与强命名依赖项不匹配,并且未能说出“无法加载Newtonsoft.Json.dll版本6.0.8”,这是正确的,因为磁盘上的版本实际上是8.0。 .2。

如果通过PackageReference使用NuGet软件包,则NuGet不仅会查看传递的NuGet依赖关系,还会查看项目依赖关系,并构建所需的所有程序集(项目或nuget)的图形。然后,MSBuild应该自动检测两个不同的程序集何时依赖于同一程序集名称的不同版本,并生成绑定重定向。因此,在使用PackageReference时,通常应该不会有问题。

但是,如果您使用packages.config定义您的NuGet依赖项,则当NuGet检测到版本冲突(我认为您可以选择退出)时,它将尝试添加绑定重定向。但是由于这是在您修改该项目中的NuGet依赖项(安装,升级或卸载程序包)时计算得出的,因此有可能使绑定重定向不同步,并且项目之间存在一个问题,即项目对项目的依赖项以及哪些NuGet会打包这些依赖项项目引用使用。

无论如何,我希望这能解释为什么当您所有项目的NuGet依赖项> = 6.0.8时,您都会收到dll加载错误。我再次重复说,程序集版本和NuGet版本是不同的东西,即使它们具有相同的值,并且.NET运行时允许您同时加载同一程序集的不同版本,并且在不需要时需要指示,这就是绑定重定向。