【问题标题】:Unable to consolidate NuGet package transitive dependency versions in two NET Standard projects无法在两个 NET Standard 项目中合并 NuGet 包传递依赖项版本
【发布时间】:2022-04-13 23:28:56
【问题描述】:

将 EF Core 添加到 NET Standard 项目会引入与其他项目中的 NuGet 包不兼容的传递依赖版本

我有一个包含多个 .NET Standard 2.0 项目的解决方案。

一个项目A使用Google.Protobuf (3.11.2) NuGet包,它依赖于

System.Memory (4.5.3)
    System.Buffers (4.4.0)
    System.Numerics.Vectors (4.4.0)
    System.Runtime.CompilerServices.Unsafe (4.5.2)

其他一些项目也依赖于System.Memory,并且都使用相同的依赖版本

另一个项目B使用Microsoft.EntityFrameworkCore (3.1.0) NuGet包,依赖于

System.Memory (4.5.3)
    System.Buffers (4.5.0)
    System.Numerics.Vectors (4.5.0)
    System.Runtime.CompilerServices.Unsafe (4.7.0)

尽管System.Memory 的版本在这两种情况下都是(4.5.3),但它依赖于System.BuffersSystem.Numerics.VectorsSystem.Runtime.CompilerServices.Unsafe,并且它们的版本不同。

当我运行使用这些项目的应用程序(使用 Unity IoC 的 Microsoft Prism WPF .NET Framework 4.8 应用程序)时,UnityContainer 会引发以下异常:

System.IO.FileLoadException: '无法加载文件或程序集 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 或其依赖项之一。找到的程序集的清单定义与程序集引用不匹配。

搜索解决方案后,我将此添加到我的 NuGet.Config:

  <config>
    <add key="DependencyVersion" value="Highest" />
  </config>

%appdata%\Nuget.sln 文件的根文件夹中。

我还删除了%userprofile%\.nuget\packages 文件夹。

然后我从项目中删除了 NuGet 包并重新添加了它们,但它们的依赖项与以前的版本相同。

如果我在 Visual Studio 中导航到“为解决方案管理 NuGet 包...”并选择“合并”,它只会显示“未找到包”

【问题讨论】:

  • 你的意思是你有两个相同版本的 System.Memory 取决于不同的包版本??
  • @PabloRecalde 是的,这正是我的意思。但我没有安装 System.Memory 所以我无法控制它的版本 - 它是作为 Google.ProtobufMicrosoft.EntityFrameworkCore 的依赖项安装的
  • 好像微软搞砸了版本......这对我来说没有任何意义
  • @panoskarajohn 我的 .net 标准项目不引用 .net 核心包 - Microsoft.EntityFrameworkCore 是一个 .net 标准库;)如果您不相信,您可以在 3 分钟内轻松重现我的问题我:)
  • @Jinjinov 哦,那真是太糟糕了。最后一个想法:blog.yaakov.online/… 我希望这能让你继续前进,因为它特别提到了底部的类库。如果没有,对不起,我帮不上忙,我希望你能尽快找到解决方案! :)

标签: c# visual-studio entity-framework-core prism unity-container


【解决方案1】:

我设法重现了这个问题。 我创建了两个新的.net standard 2.0 project 类库。

在第一个我添加了EF Core。 第二次我添加了Google protobuf

与您提到的两个版本相同。

对于 EF 核心,我创建了一个仅继承自 DbContext 的新类。 对于 Protobuf,我刚刚创建了一个空类,因为我不熟悉如何使用它。 不过,我仍然能够复制该问题。

然后我创建了一个console app .net framework 4.7.2 引用上述两个项目。

我在Console App中实例化了这两个类,得到error System.IO.FileLoadException: 'Could not load file or assembly...

我是如何解决的

我去了所有三个项目并将这一行添加到csproj

&lt;RestoreProjectStyle&gt;PackageReference&lt;/RestoreProjectStyle&gt;

到属性组。

<PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>

之后我再次构建并运行,没有出现错误。

请告诉我你的结果。 即使我的解决方案不适合您,我相信拥有它也是一种好习惯。

引用奥伦的话。
“使用 .NET Standard 要求您使用 PackageReference 来消除“大量包”带来的痛苦,并正确处理传递依赖项。虽然您可以在没有 PackageReference 的情况下使用 .NET Standard,但我不推荐它。”

Hanselman 还提到: ““完整”框架项目使用较旧的 .csproj 格式,默认情况下,它们使用 package.config 来管理依赖项。较新的项目可以将 Packages 引用为一流的引用。所以我们需要告诉这个解决方案中的所有项目以“PackageReferences”的形式管理和恢复他们的包。”

这是我的来源。

https://www.hanselman.com/blog/ReferencingNETStandardAssembliesFromBothNETCoreAndNETFramework.aspx

https://oren.codes/2017/04/23/using-xamarin-forms-with-net-standard-vs-2017-edition/

根据来自github issues 的 Sommen 的额外信息进行了更新 感谢 Sommen 提供这些额外信息。还要感谢 Immo Landwerth 在 GitHub 上提供此信息。 按照 OP jinjinov 的建议,我将按原样提供 Github 页面中已经存在的解决方法。

取自GitHub Issues

解决方法

常规 .NET Framework 项目

  1. 在根 .NET Framework 应用程序中启用 automatic binding redirects
  2. 确保您的根应用程序项目不使用packages.config,而是将PackageReference 用于NuGet 包:
    • 如果您目前没有packages.config,只需添加 &lt;RestoreProjectStyle&gt;PackageReference&lt;/RestoreProjectStyle&gt;
    • 如果您当前有packages.config,请将内容转换为项目文件中的包引用。语法是这样的: &lt;PackageReference Include="package-id" Version="package-version" /&gt;

ASP.NET Web 应用程序和网站

  1. Web 应用程序和网站不支持自动绑定重定向生成。为了解决绑定冲突,您需要双击错误列表中的警告,Visual Studio 会将它们添加到您的 web.config 文件中
  2. 在 Web 应用程序项目中,您应该像上面提到的那样启用 PackageReference。在网站中,您不能使用 PackageReference,因为没有项目文件。在这种情况下,您需要将所有直接或间接项目引用所依赖的所有 NuGet 包安装到您的网站中。

单元测试项目

默认情况下,绑定重定向不会添加到类库项目中。这对于单元测试项目来说是有问题的,因为它们本质上就像应用程序。因此,除了automatic binding redirects 中概述的内容之外,您还需要指定GenerateBindingRedirectsOutputType

<PropertyGroup>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

还有一个讨论部分提供更多信息 -> GitHub discussion

【讨论】:

  • 谢谢!阅读来自 sommmen github.com/dotnet/announcements/issues/31 的链接,我发现您的解决方案适用于没有任何 NuGet 包的项目——在 GitHub 问题上,请参阅 Workarounds,第 2 点。——我假设您没有在控制台应用程序中包含任何内容?如果您更新您的答案以包含所有解决方法,我会接受它,因为您在 sommmen 之前写了它:)
  • @Jinjinov 谢谢,我已更新答案以提供完整信息。如果你觉得还有更多。不要犹豫,编辑和更新。
【解决方案2】:

是的,欢迎参加战斗。

就像 PanosKarajohn 指出的那样,使用 packagereference 而不是 packages.config 有助于解决这个问题。不幸的是,这是 Vs2017 及更高版本,对于我们中的一些人来说还没有看到。

这个问题实际上在这里解释得差不多了: https://github.com/dotnet/announcements/issues/31

您需要使用绑定重定向将所有版本号重定向到您所获得的最高版本号,然后祈祷一切都能很好地相互配合。

我在 .net 4.6.1 项目中使用 Microsoft.aspnetcore.signalR 包,您也有同样的问题。

【讨论】:

  • 不错!这是来自 GitHub 的一篇非常好的帖子。
  • 按照 OP 的建议,我已更新我的答案以包含您的链接以确保完整性。
  • 是的。实际上,我可能花了 3 天左右的时间来解决这个问题,特别是因为我们正处于需要支持 vs2015 和 vs2019 的时间点。我实际上有一个类库,它运行一个脚本,该脚本创建一个 {name}.exe.config 文件来处理所有绑定重定向。然后将其复制到可执行项目中(我们祈祷所有版本都向后兼容)。我希望我们可以在某个时间点将所有内容升级到 .net 标准和核心。恭喜当之无愧的赏金,希望我们都从这次努力中学到了很多:)
  • 谢谢。我确实学到了很多东西。随时编辑我的答案并附加到它:)
猜你喜欢
  • 2018-01-22
  • 2023-03-09
  • 2019-03-19
  • 2017-07-18
  • 1970-01-01
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 2018-11-15
相关资源
最近更新 更多