Friday, July 13, 2012

How To: Configuration Based References

So you want to include/exclude references based on your solution configuration. In Visual Studio you can specify solution configuration modes and in the properties of your projects you can have their settings differ based on the mode you put your solution into. For instance, if you have code that only should be run in debug mode, you can place a fragment of code that gets built when your solution is in debug mode. When you select release mode, this fragment is skipped during the build process and your application is none the wiser.

What happens when you are working with a web solution? Same thing. What if you wanted to run Phil Haacks' Route Debugger? Well you can include the library and set everything up just as his tutorial explains. But every time you want to turn it on/off you have to edit your file. You can create a special Configuration for your solution that can handle enabling/disabling this. The solution is simple, yet a little tedious since there is no IDE interface for what I am about to suggest.

Your projects CSPROJ file defines all the details about your references. A CSPROJ file is just an XML file that describes a single project. It also has a conditional attribute that you can apply to many of the tags within. Here is the solution.
  1. Open our project and create a few external references.
  2. We need to have a solution mode to test against so lets create a new solution configuration "DebugComponent". Inherit from debug because we are just modifying that one.
  3. We should designate a few destinations for our files per mode. In the projects properties open the build tab and change the output directory for each mode to be "bin\<mode>". We should have 3 modes right now.
  4. Keep the VS session open so it can react to our changes to the CSPROJ file and debug our updates.
  5. Now that we are all set up, lets get dirty and open that CSPROJ file in a text/XML editor. Notepad++ works great.
  6. Find the section for the references. if you search for: <Reference Include="Microsoft.CSharp" /> you should end up exactly where you need to be.
  7. Now find your references in this list. For each one you notice they have children nodes. One of these children, if present, should be <Private>True</Private>. This is where we apply our changes.
  8. Now all we need to do is place a conditional in this location and all will be done. Change the private tag to be:
    <Private Condition="'$(Configuration)' != 'DebugComponent' or '$(Configuration)' != 'ReleaseComponent'">True</Private>
    <Private Condition="'$(Configuration)' == 'DebugComponent' or '$(Configuration)' == 'ReleaseComponent'">False</Private>

  9. Now what about having a second one? Maybe we want a release mode for our component build. Set up another configuration called: "ReleaseComponent" and then update the CSPROJ file respectively to the following.
    <Private Condition="'$(Configuration)' != 'DebugComponent' or '$(Configuration)' != 'ReleaseComponent'">True</Private>
    <Private Condition="'$(Configuration)' == 'DebugComponent' or '$(Configuration)' == 'ReleaseComponent'">False</Private>

Simple, yet a bit manual. You will have to do this for each of your references. Until I find a solution that allows the IDE to do this, perhaps maybe a plug-in, this will allow you to build the expected DLLs into the correct bin location.

When you build with one of these modes you get all the DLLs for your application when you build in standard debug and release mode. In our variant of the solution configurations, you will only get the ones that you have specified.

Awesome interdependance built into the solution manager with minimal pain, and you don't have to write a crazy post build script to handle this all for you making sure you have the expected files and having to update the script. Just updating the solution file to work for you should be fine.

No comments:

Ajax Lesson

NOTE : This lesson uses jQuery as the interface for basic AJAX work. By no means is AJAX a product of jQuery and you do not need jQuery to ...