Search code examples
c#nuget-packageprojects-and-solutionstarget-framework

Is there any reliable (even standardized) approach to creating a .NET library that supports multiple target frameworks simultaneously?


I understand this is quite a general question but I've not been able to find a reliable resource on solving the following scenario, nor it has been in one place. So I decided to ask here in the hopes to help others struggling with the same issue:

As a developer of .NET components I want to support a wide variety of .NET target frameworks. This topic had become quite important for me as of the recent explosion of target framework variants when dot net core and the dot net standard have been introduced.

So, imagine I am writing a C# library MyLib (that I would refer to as "product") which compiles to the MyLib.dll. I want to support the different range of target frameworks: net35, net40, net45, netstandard1.2 and etc. Therefore I create builds (MSBuild or csproj files) for each target framework and bundle them together in a single nuget package, respecting the nuget guidelines for the lib folder structure. Thus the product can be obtained from a single build artefact -- the nuget package.

For each target framework version I try to utilize its features and benefits and provide pollyfills for the lower versions or strip some features. In general the point is that the "product" is usable regardless of the consuming project's target framework -- I mean the nuget package for MyLib should install correctly, and the appropriate dll should be referenced.

So, a few questions arise:

  • Is it correct to share the same assembly version info across the different builds? Like re-using the same AssemblyInfo.cs file?
  • Which assembly attributes should not be shared between my builds? I have started another thread in regards to the [assembly: Guid("...")]] attribute. Other people are displaying concerns of the [assembly: AssemblyTitle("...")] attribute as well, while in a different context.
  • Is there any good or standardized approach of organizing a solution to support the described above build outcome. Do most projects out there really fend for themselves in achieving this?

My own way so far is to use a separate .csproj file per target framework for the same "product", but as the development progresses, it could become tedious to support multiple projects, even so as the target framework count is quite significant now.


Solution

  • Therefore I create builds (MSBuild or csproj files) for each target framework and bundle them together in a single nuget package.

    If you are using the new csproj "SDK" format from Visual Studio 2017 then you don't even need to do that - it supports multiple target frameworks. For example:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
       <TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
      </PropertyGroup>
    </Project>
    

    This project supports both the .NET Framework 4.5.1 and NETStandard1.3.

    This automatically creates conditional compilation symbols so you can do things like #if NET451 or #if NETSTANDARD1_3 so you can conditionally apply code, if needed. You can likewise do this in the .csproj itself for including nuget packages for only one framework. The Dapper project has an example of this in their .csproj file.

    Using the new dotnet cli, you can use dotnet pack to package it all up in to a nuget package.