无法合并两个 NET Standard 项目中的 NuGet 包传递依赖版本
Unable to consolidate NuGet package transitive dependency versions in two NET Standard projects
将 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.Buffers
、System.Numerics.Vectors
和 System.Runtime.CompilerServices.Unsafe
并且它们的版本不同。
当我 运行 使用这些项目的应用程序(使用 Unity IoC 的 Microsoft Prism WPF .NET Framework 4.8 应用程序)时,UnityContainer 抛出以下异常:
System.IO.FileLoadException: 'Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.
在搜索解决方案后,我将其添加到我的 NuGet.Config:
<config>
<add key="DependencyVersion" value="Highest" />
</config>
在 %appdata%\Nuget
和 .sln
文件的根文件夹中。
我还删除了 %userprofile%\.nuget\packages
文件夹。
然后我从项目中删除了 NuGet 包并再次添加它们,但是它们的依赖项与以前的版本相同。
如果我导航到 Visual Studio 中的 "Manage NuGet Packages for Solution..." 并选择 "Consolidate" 它只会显示 "No packages found"
我设法重现了这个问题。
我创建了两个新的 .net standard 2.0 project
class 库。
在第一个我添加了 EF Core
。
在第二个我添加了 Google protobuf
.
与您提到的两个版本相同。
对于 EF 核心,我创建了一个新的 class,它只是继承自 DbContext
。
对于 Protobuf,我刚刚创建了一个空的 class,因为我不熟悉如何使用它。
不过,我仍然能够重现该问题。
然后我创建了一个console app .net framework 4.7.2
引用上面两个项目。
我在控制台应用程序中实例化了两个 classes 并获得了 error System.IO.FileLoadException: 'Could not load file or assembly...
我是怎么解决的
我去了 所有三个 项目并将此行添加到 csproj
。
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
加入 属性 组。
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
之后我再次构建 运行 并且没有出现错误。
请告诉我您的结果。
即使我的解决方案对您不起作用,我相信拥有它也是一种很好的做法。
To quote Oren.
"Using .NET Standard requires you to use PackageReference to eliminate the pain of “lots of packages” as well as properly handle transitive dependencies. While you may be able to use .NET Standard without PackageReference, I wouldn’t recommend it."
Also Hanselman mentions:
"The "full" Framework projects are using the older .csproj format and by default, they use package.config to manage dependencies. The newer projects can reference Packages as first-class references. So we need to tell ALL projects in this solution to manage and restore their packages as "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 for providing this extra info. Also Kudos to Immo Landwerth 在 GitHub 提供此信息。
我将按照 OP jinjinov 的建议提供 Github 页面中已经存在的变通办法,只是为了复杂性。
解决方法
常规 .NET Framework 项目
- 在根 .NET Framework 应用程序中启用 automatic binding redirects
- 确保您的根应用程序项目不使用
packages.config
但对 NuGet 包使用 PackageReference
:
- 如果您目前没有
packages.config
,只需添加
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
.
- 如果您目前有
packages.config
,请将内容转换为项目文件中的包引用。语法是这样的:
<PackageReference Include="package-id" Version="package-version" />
ASP.NET 网络应用程序和网站
- Web 应用程序和网站不支持自动绑定重定向生成。为了解决绑定冲突,您需要双击错误列表中的警告,Visual Studio 会将它们添加到您的 web.config 文件中
- 在网络应用程序项目中,您应该像上面提到的那样启用 PackageReference。在网站中,您不能使用 PackageReference,因为没有项目文件。在这种情况下,您需要将所有 NuGet 包安装到任何直接或间接项目引用所依赖的网站中。
单元测试项目
默认情况下,绑定重定向不会添加到 class 库项目中。这对于单元测试项目来说是有问题的,因为它们本质上就像应用程序。因此,除了 automatic binding redirects 中概述的内容之外,您还需要指定 GenerateBindingRedirectsOutputType
:
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
还有一个提供更多信息的讨论部分 -> GitHub discussion
是啊,欢迎加入奋斗。
就像 PanosKarajohn 指出的那样,使用 packagereference 而不是 packages.config 有助于解决这个问题。不幸的是,这是 Vs2017 及更高版本,对于我们中的一些人来说还没有出现。
问题实际上在这里得到了很好的解释:
https://github.com/dotnet/announcements/issues/31
您需要使用绑定重定向将所有版本号重定向到您获得的最高版本号,然后祈祷一切都能相互配合。
我在 .net 4.6.1 项目中使用 Microsoft.aspnetcore.signalR 包,您遇到了同样的问题。
将 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)
依赖于
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.Buffers
、System.Numerics.Vectors
和 System.Runtime.CompilerServices.Unsafe
并且它们的版本不同。
当我 运行 使用这些项目的应用程序(使用 Unity IoC 的 Microsoft Prism WPF .NET Framework 4.8 应用程序)时,UnityContainer 抛出以下异常:
System.IO.FileLoadException: 'Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.
在搜索解决方案后,我将其添加到我的 NuGet.Config:
<config>
<add key="DependencyVersion" value="Highest" />
</config>
在 %appdata%\Nuget
和 .sln
文件的根文件夹中。
我还删除了 %userprofile%\.nuget\packages
文件夹。
然后我从项目中删除了 NuGet 包并再次添加它们,但是它们的依赖项与以前的版本相同。
如果我导航到 Visual Studio 中的 "Manage NuGet Packages for Solution..." 并选择 "Consolidate" 它只会显示 "No packages found"
我设法重现了这个问题。
我创建了两个新的 .net standard 2.0 project
class 库。
在第一个我添加了 EF Core
。
在第二个我添加了 Google protobuf
.
与您提到的两个版本相同。
对于 EF 核心,我创建了一个新的 class,它只是继承自 DbContext
。
对于 Protobuf,我刚刚创建了一个空的 class,因为我不熟悉如何使用它。
不过,我仍然能够重现该问题。
然后我创建了一个console app .net framework 4.7.2
引用上面两个项目。
我在控制台应用程序中实例化了两个 classes 并获得了 error System.IO.FileLoadException: 'Could not load file or assembly...
我是怎么解决的
我去了 所有三个 项目并将此行添加到 csproj
。
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
加入 属性 组。
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
之后我再次构建 运行 并且没有出现错误。
请告诉我您的结果。 即使我的解决方案对您不起作用,我相信拥有它也是一种很好的做法。
To quote Oren.
"Using .NET Standard requires you to use PackageReference to eliminate the pain of “lots of packages” as well as properly handle transitive dependencies. While you may be able to use .NET Standard without PackageReference, I wouldn’t recommend it."
Also Hanselman mentions: "The "full" Framework projects are using the older .csproj format and by default, they use package.config to manage dependencies. The newer projects can reference Packages as first-class references. So we need to tell ALL projects in this solution to manage and restore their packages as "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 for providing this extra info. Also Kudos to Immo Landwerth 在 GitHub 提供此信息。 我将按照 OP jinjinov 的建议提供 Github 页面中已经存在的变通办法,只是为了复杂性。
解决方法
常规 .NET Framework 项目
- 在根 .NET Framework 应用程序中启用 automatic binding redirects
- 确保您的根应用程序项目不使用
packages.config
但对 NuGet 包使用PackageReference
:- 如果您目前没有
packages.config
,只需添加<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
. - 如果您目前有
packages.config
,请将内容转换为项目文件中的包引用。语法是这样的:<PackageReference Include="package-id" Version="package-version" />
- 如果您目前没有
ASP.NET 网络应用程序和网站
- Web 应用程序和网站不支持自动绑定重定向生成。为了解决绑定冲突,您需要双击错误列表中的警告,Visual Studio 会将它们添加到您的 web.config 文件中
- 在网络应用程序项目中,您应该像上面提到的那样启用 PackageReference。在网站中,您不能使用 PackageReference,因为没有项目文件。在这种情况下,您需要将所有 NuGet 包安装到任何直接或间接项目引用所依赖的网站中。
单元测试项目
默认情况下,绑定重定向不会添加到 class 库项目中。这对于单元测试项目来说是有问题的,因为它们本质上就像应用程序。因此,除了 automatic binding redirects 中概述的内容之外,您还需要指定 GenerateBindingRedirectsOutputType
:
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
还有一个提供更多信息的讨论部分 -> GitHub discussion
是啊,欢迎加入奋斗。
就像 PanosKarajohn 指出的那样,使用 packagereference 而不是 packages.config 有助于解决这个问题。不幸的是,这是 Vs2017 及更高版本,对于我们中的一些人来说还没有出现。
问题实际上在这里得到了很好的解释: https://github.com/dotnet/announcements/issues/31
您需要使用绑定重定向将所有版本号重定向到您获得的最高版本号,然后祈祷一切都能相互配合。
我在 .net 4.6.1 项目中使用 Microsoft.aspnetcore.signalR 包,您遇到了同样的问题。