Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Microsoft.Extensions.* version confusion

Tags:

asp.net-core

I have a library targeting netstandard2.0 that I use in a ASP.NET Core 2.2 application that relies on a couple of Microsoft.Extensions packages

Here is my 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>

I now want to be able to use this same library in a new ASP.NET Core 3 application as well as my existing ASP.NET Core 2.2 applications.

Looking at the Microsoft.Extensions.* packages, their versions always appear to match the release versions of ASP.NET Core.

My options are

  • Do nothing .. Will this package still work in an ASP.NET Core 3 application?
  • Upgrade the packages to their 3.0 equivalents .. Will this package still work in an ASP.NET Core 2 application?
  • Keep the existing package (for ASP.NET Core 2.2 applications), but create a new package using the 3.0 equivalents for use in ASP.NET Core 3.0 applications

The overall question is as a library author, what is the correlation between a specific version of a Microsoft.Extensions.* package and its use within a specific ASP.NET Core target?

like image 266
kimsagro Avatar asked Oct 01 '19 22:10

kimsagro


2 Answers

You can (and should) do multi-targeting.

Target netstandard2.0 and netstandard2.1, for netstandard2.0 reference the 2.x (lowest one which works for you, prob 2.0, there should be no breaking changes in 2.x) and for netstandard2.1 reference the 3.x versions of it.

Why?

Because its a major version jump, usually ending up with new apis, removal of old or change of method signatures (in other words: breaking changes) and since netstandard2.1 requires .NET Core 3.0 so also applications referencing it rely on Microsoft.Extensions.* 3.x version APi surface

To conditionally reference a package, do

<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>

Alternatively

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

works too, but its less readable. This will still create one NugetPackage, but it will have two folders netstandard2.0 and netstandard2.1 with two separately complied assemblies targeting the different versions.

When this package is restored on .NET Core 3, it will use the netstandard2.1 version, if restored on .NET Core 2.x it will use netstandard2.0.

If there are api differences, you have to use preprocessor directives in your code

#if NETSTANDARD2_0
    // API call of 2.x library
#elif NETSTANDARD2_1
    // Api call of 3.x library
#endif
like image 179
Tseng Avatar answered Nov 03 '22 06:11

Tseng


with reference to your options:

Do nothing .. Will this package still work in an ASP.NET Core 3 application?

Can't give exact answer, it depends on the classes availability in the target framework, you may check in .NET API Browser for all .NET versions

Upgrade the packages to their 3.0 equivalents .. Will this package still work in an ASP.NET Core 2 application?

No, when you target a higher version it will try to install all related dependencies from the higher versioned framework as well, and this will make a lot of confusion.

Keep the existing package (for ASP.NET Core 2.2 applications), but create a new package using the 3.0 equivalents for use in ASP.NET Core 3.0 applications

This can solve the issue but it is not a practical solution, you will double the work when you work on any updates.

As mentioned in the previous comment, you can do multiple target nuget package (consider this option only if you need framework specific dependencies)

@Tseng already explained the conditional targeting, I will add only the targeting for .NET Core 3, since most of the nuget packages are already included in the core 3 framework you may only need to add framework reference as below:

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" Version="3.0.0" Exclude="Build,Analyzers" />
</ItemGroup>
like image 45
LazZiya Avatar answered Nov 03 '22 05:11

LazZiya