What's the best way to target multiple versions of the .NET framework?

I'm building a class library and I will deploy it a NuGet package, which lets me choose different assemblies to be added as references based on the .NET framework version of the project it's added to. This is a very nice feature, but what I'm wondering is whether it is possible to have a single class library project, and build it against mulitple versions of the .NET framework?

I'd rather avoid having:

MyLibrary40.dll and MyLibrary45.dll

if possible, because the two projects would have to share a lot of code. The 4.5 version will be offering async functions, which is a 4.5 feature.

Does anyone know what the best approach for this is? Can I use multiple build configurations? Or must I go down the separate project route?

If I was working in C++ I'd probably use multiple configurations and #if blocks around the functions that are only supported in one configuration, but I worry this would lead to me having two assemblies with the same name that do different things.

Thanks in advance!


You will at least need one VisualStudio Solution with 2 projects (one for .net 4 and one for .net 4.5).

Add all codefiles to the .net 4-project and in the other project you add the code files as link (use "Add Existing Item..."-Dialog and chose Add as link)

Now you add all codes and classes for .NET 4.5 to your 4.5-project.

Additionally you should define your own compiler switches (conditional compilation symbols) to your projects. Like NET4 for your .net 4-project and NET4.5 to your .net 4.5-project)

You set the switches in the project settings under Build->General->Conditional Compilation Switches

In your code you can use the switches as follows to generate code for .NET 4 or .NET 4.5

#if NET4
  // code only for .NET 4
#endif

// code for all framework versions.

#if NET45
  // code only for .NET 4.5
#endif

A simple approach is to add another .csproj file in the same folder, and configure it to build a different framework version. This avoids having to add links to files, as both projects are essentially views over the same folder structure.

Say you have the structure:

- MyLibrary\
  - MyLibrary.sln
  - MyLibrary\
    - MyLibrary.csproj
    - Program.cs

Duplicate MyLibrary.csproj to the same folder and edit to change a few things:

  • <ProjectGuid> just make a new GUID for this element's value
  • <TargetFrameworkVersion> specify the alternative version here, eg: v4.5 or v3.5
  • <OutputPath> (for Debug and Release) set this to a unique path, such as bin\Debug\net45 and bin\Debug\net45, to allow each project's output to end up in a unique location

You must also add a new element to the non-conditional <PropertyGroup> element, so that the two projects don't collide in the obj folder during parallel builds. This is important, and protects against weird race condition bugs.

<PropertyGroup>
  <BaseIntermediateOutputPath>obj\net45\</BaseIntermediateOutputPath>

Finally, add this new project to your existing solution.

This approach works hand in hand with defining compilation switches such as NET35 and NET45, and using #if NET35 / #endif directives.

Two open source projects that use this technique are MetadataExtractor and NetMQ. You can refer to them in case you hit trouble.


Old question I know, and this wasn't a suitable answer at the time... but now it is possible to use a Shared Project, which is logically the same as adding a project as link rather than each file individually.