【问题标题】:Microsoft.Extensions.* version confusionMicrosoft.Extensions.* 版本混淆
【发布时间】:2020-01-31 05:33:45
【问题描述】:

我有一个针对 netstandard2.0 的库,我在依赖于几个 Microsoft.Extensions 包的 ASP.NET Core 2.2 应用程序中使用它

这是我的csproj

<Project Sdk="Microsoft.NET.Sdk">

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

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.2.0" />
  </ItemGroup>

</Project>

我现在希望能够在新的ASP.NET Core 3 应用程序以及我现有的ASP.NET Core 2.2 应用程序中使用同一个库。

查看Microsoft.Extensions.* 包,它们的版本似乎总是与ASP.NET Core 的发布版本相匹配。

我的选择是

  • 什么都不做 .. 这个包在ASP.NET Core 3 应用程序中仍然可以工作吗?
  • 将软件包升级到它们的 3.0 等效项。这个软件包在 ASP.NET Core 2 应用程序中是否仍然有效?
  • 保留现有包(用于ASP.NET Core 2.2 应用程序),但使用3.0 等效项创建一个新包以用于ASP.NET Core 3.0 应用程序

总体问题是作为库作者,Microsoft.Extensions.* 包的特定版本与其在特定ASP.NET Core 目标中的使用之间有什么相关性?

【问题讨论】:

  • 我之前发过一个相关的问题,我也不清楚。 stackoverflow.com/questions/57846163/…
  • 谢谢朱利安,会检查一下..所有这些定位都让我感到非常困惑,很高兴我并不孤单
  • 对于稍后提出这个问题的人,并且您正在尝试在 .NetStandard 2.1 库中使用 Microsoft.Extensions(可能是配置),这仍然是偶数更令人困惑。 Microsoft.Extensions 面向 .NetStandard 2.0 .NetCoreApp 3.1。所以VS告诉你'Can't use this for .NetStandard 2.1。使其成为 .netcore 应用程序',这可能会对您正在编写的其他标准库产生多米诺骨牌效应。混淆是因为 Visual Studio 没有告诉您“或者您可以定位 .NetStandard 2.0 并且很好 - 甚至可能比使用 2.1 覆盖更多的用户”。

标签: asp.net-core


【解决方案1】:

您可以(并且应该)进行多目标。

目标 netstandard2.0netstandard2.1netstandard2.0 参考 2.x(最适合你的,可能是 2.0,2.x 中应该没有重大变化),netstandard2.1 参考它的 3.x 版本。

为什么?

因为它是一个主要版本的跳转,通常以新的 API 结束,删除旧的或更改方法签名(换句话说:破坏性更改)并且由于 netstandard2.1 需要 .NET Core 3.0,所以引用它的应用程序也依赖Microsoft.Extensions.*3.x版API面

要有条件地引用包,请执行

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
     <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0"/>
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
     <PackageReference Include="Microsoft.Extensions.Logging" Version="3.0"/>
</ItemGroup>

或者

<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0" Condition=" '$(TargetFramework)' == 'netstandard2.01' "/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0" Condition=" '$(TargetFramework)' == 'netstandard2.1' "/>

也可以,但它的可读性较差。这仍将创建一个 NugetPackage,但它将有两个文件夹 netstandard2.0netstandard2.1 以及两个针对不同版本的单独编译的程序集。

当这个包在 .NET Core 3 上恢复时,它将使用 netstandard2.1 版本,如果在 .NET Core 2.x 上恢复,它将使用 netstandard2.0

如果存在 api 差异,则必须在代码中使用预处理器指令

#if NETSTANDARD2_0
    // API call of 2.x library
#elif NETSTANDARD2_1
    // Api call of 3.x library
#endif

【讨论】:

  • Microsoft.Extensions.Logging为例。 v3.0 版增加了一些额外的成员 (fuget.org/packages/Microsoft.Extensions.Logging/3.0.0/lib/…) 并针对 netstandard 2.0。如果我采用您建议的方法,那么附加功能只有在 NET Core 3 引用时才可用,而实际上它可用于所有 netstandard 2.0 目标。因此,在这种情况下,以netstandard2.0 为目标并使用Microsoft.Extensions.Logging" Version="3.0" 似乎是两全其美。我的想法对吗?
【解决方案2】:

参考您的选择:

什么都不做 .. 这个包在 ASP.NET Core 3 应用程序中仍然可以工作吗?

无法给出确切答案,这取决于目标框架中的类可用性,您可以在.NET API Browser 中查看所有 .NET 版本

将包升级到它们的 3.0 等效版本.. 这个包是否仍然可以在 ASP.NET Core 2 应用程序中工作?

不,当您以更高版本为目标时,它也会尝试安装来自更高版本框架的所有相关依赖项,这会造成很多混乱。

保留现有包(用于 ASP.NET Core 2.2 应用程序),但使用 3.0 等效项创建一个新包以用于 ASP.NET Core 3.0 应用程序

这可以解决问题,但不是一个实用的解决方案,当您进行任何更新时,您将加倍工作。

正如前面评论中提到的,你可以做多个目标 nuget 包(仅当你需要特定于框架的依赖项时才考虑这个选项)

@Tseng 已经解释了条件定位,我将只添加 .NET Core 3 的定位,因为大部分nuget packages are already included in the core 3 framework 您可能只需要添加如下框架引用:

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" Version="3.0.0" Exclude="Build,Analyzers" />
</ItemGroup>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多