views:

382

answers:

1

There are a few minor places where code for my project may be able to be drastically improved if the target framework were a newer version. I'd like to be able to better leverage conditional compilation in C# to switch these as needed.

Something like:

#if NET40
using FooXX = Foo40;
#elif NET35
using FooXX = Foo35;
#else NET20
using FooXX = Foo20;
#endif

Do any of these symbols come for free? Do I need to inject these symbols as part of the project configuration? Seems easy enough to do since I'll know which framework is being targeted from MSBuild.

/p:DefineConstants="NET40"

Update: My question is how are people handling this situation? Are you creating different configurations? Are you passing in the constants via the command line?

+4  A: 

One of the best ways to accomplish this is to create different build configurations in your project:

<PropertyGroup Condition="  '$(Framework)' == 'NET20' ">
  <DefineConstants>NET20</DefineConstants>
  <OutputPath>bin\$(Configuration)\$(Framework)</OutputPath>
</PropertyGroup>


<PropertyGroup Condition="  '$(Framework)' == 'NET35' ">
  <DefineConstants>NET35</DefineConstants>
  <OutputPath>bin\$(Configuration)\$(Framework)</OutputPath>
</PropertyGroup>

And in one of your default configurations:

<Framework Condition=" '$(Framework)' == '' ">NET35</Framework>

Which would set the default if it wasn't defined anywhere else. In the above case the OutputPath will give you a separate assembly each time you build each version.

Then create a AfterBuild target to compile your different versions:

<Target Name="AfterBuild">
  <MSBuild Condition=" '$(Framework)' != 'NET20'"
    Projects="$(MSBuildProjectFile)"
    Properties="Framework=NET20"
    RunEachTargetSeparately="true"  />
</Target>

This example will recompile the entire project with the Framework variable set to NET20 after the first build (compiling both and assuming that the first build was the default NET35 from above). Each compile will have the conditional define values set correctly.

In this manner you can even exclude certain files in the project file if you want w/o having to #ifdef the files:

<Compile Include="SomeNet20SpecificClass.cs" Condition=" '$(Framework)' == 'NET20' " />

or even references

<Reference Include="Some.Assembly" Condition="" '$(Framework)' == 'NET20' " >
  <HintPath>..\Lib\$(Framework)\Some.Assembly.dll</HintPath>
</Reference>
Todd
Perfect. I had just enough experience hacking the msbuild format to know it could be done, but not enough time to figure out all the details. Thank you very much!
McKAMEY
If you add a reference to this answer over on my related question (http://stackoverflow.com/questions/2923181), I'll mark you as the solution there. This actually solves both of them at the same time.
McKAMEY