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
orv3.5
-
<OutputPath>
(for Debug and Release) set this to a unique path, such asbin\Debug\net45
andbin\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.