同一解决方案中两个不同项目的相同 Nuget 包
Same Nuget package on two different projects in same solution
我在同一个解决方案中有两个 API 项目(一个是我的,另一个我需要参考并且不应该更改)。这两个 API 项目都添加了对 Ninject
和 Ninject.Web.Common
包的引用。以下是软件包的设置方式:
Ninject.Web.Common
在网络中 Api A - \packages\Ninject.Web.Common.3.3.2\lib\net45\Ninject.Web.Common.dll
Ninject.Web.Common
网络 Api B - \packages\Ninject.Web.Common.3.2.3.0\lib\net45-full
(注意版本不同 3.3.2
和 3.2.3
)
当我尝试运行我的解决方案时发生的事情是
Could not load type 'Ninject.Web.Common.OnePerRequestHttpModule' from assembly 'Ninject.Web.Common, Version=3.3.2.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7'.
在我的 Web Api B
项目上(注意它试图引用我的 Web Api A
项目中的 3.3.2
版本)。
如何使两个项目保持相同并让它们引用各自的 Ninject 版本?
您通常只能解析依赖关系图中给定依赖关系的一个版本(nuget restore
主要用于计算给定依赖关系图中要使用的版本)。
这通常没问题,但您的问题是 OnePerRequestHttpModule
在 Ninject.Web.Common https://www.fuget.org/packages/Ninject.Web.Common/3.3.2/lib/netstandard2.0/diff/3.2.3/ 的 3.2.3 和 3.3.2 版本之间被删除,而 WebApiB 想要使用它。
您的选择是修改 WebApiB 使其不再使用 OnePerRequestHttpModule
,或者将 WebApiA 中的 Ninject.Web.Common 版本降级到 3.2.3
我看到您使用的是 4.5 FW 但是:
如果您已经在使用较新的 csproj 格式或者可以升级到它(这只是为了更改 csproj 的格式,项目本身仍将针对它的目标)
https://natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/
然后你可以停止依赖流到顶部(link 是针对 dotnet core,但如果项目格式是上面的新格式,那么建议仍然有效):
The way to change the default behavior is to add
<PrivateAssets>all</PrivateAssets>
for each package/project dependency inclusion.
https://curia.me/net-core-transitive-references-and-how-to-block-them/
这也适用于一些完整的 .Net FW 项目。
一旦你设法停止了依赖项的流动,你就可以将你对所需依赖项版本的引用添加到你的项目中
您可以尝试以下方法之一:
- 创建 post 将多版本程序集注册到 GAC 的构建步骤。
CLR 将在检查输出文件夹之前查看 GAC。由于两个程序集都安装在 GAC 中,运行时将找到并加载正确的版本。
- 使用 gacutil.exe 将两个程序集安装到 GAC。然而,这对于开发环境来说不是很实用,因为必须在每台机器上重复安装。
安装后,将引用的 CopyLocal 属性 设置为 False,因为它们不需要位于输出文件夹中。
- 通过 AppDomain.AssemblyResolve 事件执行自定义解析。
- 将程序集复制到不同的文件夹并指定codebase element。通过编辑 Web 应用程序配置文件,您可以将应用程序指向适当的 DLL 版本,即使它们不直接位于 bin 文件夹中。
<configuration>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SomeStrongNameLib" culture="neutral" publicKeyToken="6a770f8bdf3d476a" />
<codeBase version="1.0.0.0" href="StrongNameLibV10/SomeStrongNameLib.dll"/>
<codeBase version="1.1.0.0" href="StrongNameLibV11/SomeStrongNameLib.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
- 使用binding redirects,但我认为这不适合你的情况。
- 使用 extern Nuget 别名。
参考:
https://michaelscodingspot.com/how-to-resolve-net-reference-and-nuget-package-version-conflicts/
https://devnet.kentico.com/articles/referencing-multiple-versions-of-the-same-assembly-in-a-single-application
我在同一个解决方案中有两个 API 项目(一个是我的,另一个我需要参考并且不应该更改)。这两个 API 项目都添加了对 Ninject
和 Ninject.Web.Common
包的引用。以下是软件包的设置方式:
Ninject.Web.Common
在网络中 Api A - \packages\Ninject.Web.Common.3.3.2\lib\net45\Ninject.Web.Common.dll
Ninject.Web.Common
网络 Api B - \packages\Ninject.Web.Common.3.2.3.0\lib\net45-full
(注意版本不同 3.3.2
和 3.2.3
)
当我尝试运行我的解决方案时发生的事情是
Could not load type 'Ninject.Web.Common.OnePerRequestHttpModule' from assembly 'Ninject.Web.Common, Version=3.3.2.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7'.
在我的 Web Api B
项目上(注意它试图引用我的 Web Api A
项目中的 3.3.2
版本)。
如何使两个项目保持相同并让它们引用各自的 Ninject 版本?
您通常只能解析依赖关系图中给定依赖关系的一个版本(nuget restore
主要用于计算给定依赖关系图中要使用的版本)。
这通常没问题,但您的问题是 OnePerRequestHttpModule
在 Ninject.Web.Common https://www.fuget.org/packages/Ninject.Web.Common/3.3.2/lib/netstandard2.0/diff/3.2.3/ 的 3.2.3 和 3.3.2 版本之间被删除,而 WebApiB 想要使用它。
您的选择是修改 WebApiB 使其不再使用 OnePerRequestHttpModule
,或者将 WebApiA 中的 Ninject.Web.Common 版本降级到 3.2.3
我看到您使用的是 4.5 FW 但是:
如果您已经在使用较新的 csproj 格式或者可以升级到它(这只是为了更改 csproj 的格式,项目本身仍将针对它的目标)
https://natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/
然后你可以停止依赖流到顶部(link 是针对 dotnet core,但如果项目格式是上面的新格式,那么建议仍然有效):
The way to change the default behavior is to add
<PrivateAssets>all</PrivateAssets>
for each package/project dependency inclusion.
https://curia.me/net-core-transitive-references-and-how-to-block-them/
这也适用于一些完整的 .Net FW 项目。
一旦你设法停止了依赖项的流动,你就可以将你对所需依赖项版本的引用添加到你的项目中
您可以尝试以下方法之一:
- 创建 post 将多版本程序集注册到 GAC 的构建步骤。 CLR 将在检查输出文件夹之前查看 GAC。由于两个程序集都安装在 GAC 中,运行时将找到并加载正确的版本。
- 使用 gacutil.exe 将两个程序集安装到 GAC。然而,这对于开发环境来说不是很实用,因为必须在每台机器上重复安装。 安装后,将引用的 CopyLocal 属性 设置为 False,因为它们不需要位于输出文件夹中。
- 通过 AppDomain.AssemblyResolve 事件执行自定义解析。
- 将程序集复制到不同的文件夹并指定codebase element。通过编辑 Web 应用程序配置文件,您可以将应用程序指向适当的 DLL 版本,即使它们不直接位于 bin 文件夹中。
<configuration>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="SomeStrongNameLib" culture="neutral" publicKeyToken="6a770f8bdf3d476a" />
<codeBase version="1.0.0.0" href="StrongNameLibV10/SomeStrongNameLib.dll"/>
<codeBase version="1.1.0.0" href="StrongNameLibV11/SomeStrongNameLib.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
- 使用binding redirects,但我认为这不适合你的情况。
- 使用 extern Nuget 别名。
参考:
https://michaelscodingspot.com/how-to-resolve-net-reference-and-nuget-package-version-conflicts/
https://devnet.kentico.com/articles/referencing-multiple-versions-of-the-same-assembly-in-a-single-application