将使用哪个版本的 .NET class?

Which version of .NET class will be used?

我有一个团队在他们的应用程序中使用 .Net Core 5.0。他们从 Nuget 中提取一些包,这些包是一些 .Net Core 包的早期版本,这些包是他们正在使用的其他包的显式依赖项。例如,他们正在引入 System.Net.Http 4.3.4 (https://www.nuget.org/packages/System.Net.Http/)。同样的 class 包含在 .Net Core 5.0 中。

我的问题是:在运行时将使用哪个版本的 System.Net.Http,4.3.4 包含在应用程序附带的单独 DLL 中,还是 5.0.x 包含在主 .Net Core 库中?

这里有两部分:

  • 当多个包版本被列为依赖时,哪个是picked/used?

  • 当包是 .NET 运行时本身的一部分时,它是否优于来自 nuget.org 的包?

第一个问题在the dotnet docs中有答案:

At build time, NuGet analyzes all the packages that a project depends on, including the dependencies of dependencies. When multiple versions of a package are detected, rules are evaluated to pick one. Unifying packages is necessary because running side-by-side versions of an assembly in the same application is problematic in .NET.

换句话说,只有包裹被挑选和使用。规则描述 here。相关的是:

When the package graph for an application contains different versions of the same package, NuGet chooses the package that's closest to the application in the graph and ignores all others. This behavior allows an application to override any particular package version in the dependency graph.

In the example below, the application depends directly on Package B with a version constraint of >=2.0. The application also depends on Package A which in turn also depends on Package B, but with a >=1.0 constraint. Because the dependency on Package B 2.0 is nearer to the application in the graph, that version is used

如果您使用详细的日志记录进行构建,您应该会看到正在应用的规则以及所选择的最终版本。

对于第二个问题 - 当 class 是 .NET 的一部分(微软称之为“收件箱”)并且在 nuget.org 上可用时会发生什么 - 有点棘手。

有一个 github issue here 几个 .NET 开发人员尝试详细回答这个问题。这是相关位:

In 2.1 and above the runtime resolution is based on assembly version and file version. If the app has the same assembly as the shared framework the assembly version will be compared (based on records in .deps.json), the higher will be used. If equal, the file version is compared (again based on records in .deps.json), the higher will be used. If both versions are equal, then the file from lower level framework will be used.

So the assembly from the app is only used if it has higher version than the one in framework. On equality the framework assembly is used (we assume that if both versions are the same, then the files are basically identical).

还有这句有趣的话:

General advice is to stop using the System.Net.Http package. At best it redirects to the inbox version, at worst it causes weird conflicts.