Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a library that targets both .NET 2.0 and .NET Standard?

I have a small library that currently supports .NET 2.0+.

I don't use any features of the later framework versions so it would be nice to keep 2.0 support, but I also want to target .NET Core (or more precisely, .NET Standard).

I tried to add both frameworks to project.json:

"frameworks": {
  "net20": {},
  "netstandard1.6": {
    "imports": "dnxcore50"
  }
}

But the NuGet packages my library needs to run on .NET Standard (System.Reflection and Microsoft.AspNetCore.WebUtilities) aren't compatible with .NET 2.0.

How can I solve this issue without maintaining two completely separate projects with almost identical code?

like image 498
Botond Balázs Avatar asked Dec 31 '16 12:12

Botond Balázs


People also ask

What is the difference between creating .NET STD library and .NET Core library?

NET Core, you can build cross-platform console apps and ASP.NET Core Web applications and cloud services. . NET Standard: This is the set of fundamental APIs (commonly referred to as base class library or BCL) that all . NET implementations must implement.

Can you have multiple target frameworks?

For SDK-style projects, you can configure support for multiple targets frameworks (TFM) in your project file, then use dotnet pack or msbuild /t:pack to create the package. nuget.exe CLI does not support packing SDK-style projects, so you should only use dotnet pack or msbuild /t:pack .


2 Answers

You can't, if you depend on Microsoft.AspNetCore.* packages as the absolute minimum for supporting .NET Standard is .NET 4.5.

.NET 4.5 is the first version to include System.Runtime on which .NET Core is based on. But when you think closer about it, it also makes no sense. If you need support for ASP.NET Core within your library.

If your library is supposed to run for ASP.NET Core and ASP.NET 4 (i.e. MVC 5, WebApi 2), then you will need to use your ASP.NET Dependencies conditionally and use #if preprocessor directives.

"frameworks": {
  "net20": {
    "dependencies": {
      "NameOf.AspNetLegacyPackage": "1.2.3"
    }
  },
  "netstandard1.3": {
    "dependencies": {
      "Microsoft.AspNetCore.WebUtilities" : "1.1.0"
    },
    "imports": "dnxcore50"
  }
}

I used netstandard1.3 as that's the minimum for Microsoft.AspNetCore.WebUtilities, but depending on your other dependencies you may need to go higher or lower.

NameOf.AspNetLegacyPackage is the name of the package which contains the same functionality as Microsoft.AspNetCore.WebUtilities which you need, but which works on .NET Framework 2.0, if there is any. If not you have to remove it and write the replacement functions yourself.

Then in your code use

#if NETSTANDARD1_3
    // Code or APIs which is only available in netstandard1.3/net4.6 
    // this includes the Microsoft.AspNetCore.WebUtillities
#else
    // Use code or API which runs under .NET Framework 2.0
#endif

Alternatively, if you are going to give up the .NET Framework 2.0 support and go for 4.5.1, you can keep using Microsoft.AspNetCore.WebUtillities (see NuGet page for dependencies) it in both

"dependencies": {
  "Microsoft.AspNetCore.WebUtilities" : "1.1.0"
},
"frameworks": {
  "net451": {
  },
  "netstandard1.3": {
    "imports": "dnxcore50"
  }
}
like image 113
Tseng Avatar answered Nov 14 '22 23:11

Tseng


You can do this by putting your code into a Shared project, then created a Class Library which targets .Net 2.0, and another Class Library project which targets NetStandard. If there are things in 2.0 or Netstandard which aren't available in the other platform, you can use compiler directives to write compatible code for each.

like image 31
Andy Avatar answered Nov 14 '22 22:11

Andy