Sunday 25 January 2009

Extension Methods in .Net 2.0

I was recently reading C# in Depth by Jon Skeet and also playing with Rhino Mocks by Oren/Ayende and was struck by the power and simplicity of both Extension Methods and also Lambda expressions. These are both C# 3 compile time features which I thought would be very useful to me in my C# 2 application which sounds like a shame. Until that is I came across this blog by Daniel Moth who describes how to use Extension Methods in C# 2.0. [Actually, as Jon Skeet has pointed out, I mean using C#3 in a .Net 2.0 assembly, see his comment for a link that explains the difference.]

Once you realise that both of these features are purely compiler trickery then all you need to do is figure out how to get them to work in .Net 2 assemblies. Daniel describes how to get Extension Methods working, by defining an Attribute that is usually available to the C# compiler when building a .Net 3.0 assembly (ExtensionAttribute). The attribute needs to be defined in the System.Runtime.CompilerServices namespace rather than one of your own.

This tricks the VS2008 C# compiler into thinking that it is compiling to .Net 3 rather than .Net 2, at least as far as Extension Methods are concerned, so now it is happy for you to add the this keyword in the static methods parameter list.

Next came lambda methods, this is also compiler tricks and simply compiles to .Net 2.0 delegate code underneath. Again you need to get the compiler to think that some things not normally available to it in C# 2 are indeed available. In this case, we need a more extensive Action<> delegate. .Net 2 provies Action that allows for an action on a single class with no return value. For what I wanted, Lambdas, we needed the .Net 3 Action class. This allows you to call delegates with return types.
This class can be defined in any namespace.

My reason for wanting these capabilities was to simplify some WinForm validation code we're writing. Imagine we have a ComboBox and want to perform validation everytime the SelectedItem changes. We want to turn the background colour to be Red if there is no selected item, and to green is something in the list has been selected. If we have 3 such combos on a form, we could capture the SelectedItemChanged event for each and perform the set of checks to see if there is a selected item and then colour the backgrounds.

Or we could use an Extension Method. I now have a ComboBoxExtension class which has the following method signature


public static void InitialiseValidation(this ComboBox combo, Color defaultColor, Action rule)


This is an Extension Method on ComboBox (first parameter), defines the default, not selected colour (second parameter) and an arbitary validation rule which returns bool and acts on a ComboBox (third parameter). This means I can write the following code in the WinForm code:


someCombo.InitialiseValidation(MColourFactory.InvalidColour, c => c.SelectedItem != null);


This simply means that when the SelectedItem property on someCombo is null, it will colour the combo the InvalidColour from our colour factory (red in this case).

There are also Extension Methods to add additional rules beyond this first one as well as explicit IsValid methods that use the same rule set.

All of this runs quite happily in a C#, .Net 2.0 assembly using the VS2008 C# compiler to do it, if you're using VS2005 I suspect you're out of luck!


Tuesday 13 January 2009

Debugging Gallio tests in Visual Studio

We use the very useful Gallio unit testing framework for both our C# and C++/CLI unit tests. We then use Resharper to execute the C# tests within Visual Studio [remember to reinstall Gallio after you have installed Resharper].

But ReSharper does not work with C++/CLI so it is more difficult to run the tests within Visual Studio. Obviously the test projects produce XXXTests.dll assemblies which cannot be run directly by selecting the projects to be the "Start Up" project and pressing F5. It is possible to set the debugging properties on the project to use Gallio.Echo.exe to be the program launched by VS when F5 is pressed, passing it the test assembly name as the command line argument. This now allows you to press F5 and see all of your tests run. There are two problems with this, firstly the Command window in which they run closes at the end of the run, making it more difficult to see what passed and failed. Secondly, even though you have asked it to run in the debugger, it won't stop on any breakpoints you have set!

The way to overcome the first issue, if it is important to you, is to use the logging command line arguments and get it to log to file what has happened.

The way to overcome the second issue, which is the main reason we want to run our tests in VS to begin with, it to add the following command line argument:

/r:IsolatedAppDomain

I have no idea what this does (other than run the test in it's own app domain?), but the upshot of it is that the breakpoints become enabled and you can now debug your tests in VS. I'd have thought having a command line option "/r:EnableDebugging" or similar would be more obvious, even if all it did was set the AppDomain flag internally?

This also works well for C# projects where you do not have Resharper or TestDriven.Net.

Example command line:

"C:\Program Files\Gallio\bin\Gallio.Echo.exe" SomeUnitTests.dll /r:IsolatedAppDomain



Sunday 11 January 2009

GPS at Airports


During a recent visit to the States I flew into Washington Dullas airport. On the way home, it would appear that my Garmin 305 GPS watch became turned on in my bag, as you can see from this image, it seemed to have a fun trip around the airport before being loaded onto the aircraft!