Using Extension methods for cross-framework projects

Tue, June 19, 2007, 10:11 AM under MobileAndEmbedded
In this post I assume you have read my blog entry on Extension Methods. When I described extension methods I finished by saying:
"Overall, I like this feature *a lot* (will post some concrete examples of why in the future)."
The time has come to explain myself. I've been waiting for my MSDN magasine article to go live so it can be the first to describe the proposed usage :-)

So to quote myself from the article:
"While using .NET Compact Framework classes, the occasion often arises that a particular class has members missing compared to the full Framework. Typically, developers have to write the missing functionality themselves and then decide whether to use inheritance if possible to add the missing members or add them to a utility helper class."
Please visit the article to see a good example of how extension methods can help with the above scenario.

When we faced this issue in the SDF from OpenNETCF, we took one decision in some cases (utility classes) and the other decision (inheritance) in other cases. Unfortunately, utility classes suffer from the inherent non-discoverability for client code and inheritance is not always possible due to sealed classes. So many times we opted for a 3rd approach (that I was never entirely comfortable with): Introducing a replacement class e.g. TextBox2. Now, there are still scenarios where that approach is the only viable technique, but for some cases using the Extension methods as I describe in the article is a better alternative.

I'll just give one more example here. If we wanted the System.Windows.Forms.Timer class in the NETCF to have a compatible interface with the desktop version, one thing we'd have to do is add Start and Stop methods. Easily achieved by dropping the following code file in just the device project and not the desktop project:
public static class TimerExtensions
{
public static void Start(this Timer t)
{
t.Enabled = true;
}
public static void Stop(this Timer t)
{
t.Enabled = false;
}
}
...and then the codefile that uses the Timer can be the same on both platforms, e.g.
private void menuItem1_Click(object sender, EventArgs e)
{
timer1.Start();
}

private void menuItem2_Click(object sender, EventArgs e)
{
timer1.Stop();
}
We have seemingly added extra methods to a class so our utility methods are discoverable and if the real NETCF class ever got those methods implemented, our code gracefully bows out at runtime. Try it out... coding is believing how cool this is :)