In my first post about Paint.NET v4, I mentioned that I was learning a lot about C# 3.0 and .NET 3.5. One of the things I’m absolutely falling head-over-heels for is extension methods.

One use of these is to add utility functionality on to existing classes that you don’t own the implementation for. As an example, consider the System.Uri class. In my opinion, it could use an Append method:

public static class UriExtensions
{
    public static Uri Append(this Uri baseUri, string relativePath)
    {
        return new Uri(baseUri, relativePath);
    }
}

You can then use code such as this:

Uri donateUri = new Uri("http://www.getpaint.net").Append("/donate.html");

Instead of:

Uri donateUri = new Uri(new Uri("http://www.getpaint.net"), "/donate.html");

(Bear in mind that the string literals would probably be pulled out of a list of constants, and not inlined like in the code above.) In this case, we’re simply enabling a choice of coding style and not really doing anything new. We are avoiding pathological nesting such as "new Uri(new Uri(new Uri(…" for when we need to paste together multiple relative Uri paths.

One place I’m finding extensions methods to be very useful is in defining and implementing interfaces with only strictly orthogonal functionality. You don’t need to add utility methods to interfaces, you can simply define them as extension methods.

For example, my resource manager is contained in an IResourcesService interface that has GetString() and GetBinaryStream() methods. And that’s it.

using System.IO;

namespace PaintDotNet.Framework
{
    public interface IResourcesService
    {
        string GetString(string stringID);
        Stream GetBinaryStream(string streamID);
    }
}

All resources other than strings are stored as binary streams, such as icons, bitmaps, text files, etc. If you want to load a bitmap, then you can use the handy extension method:

using System.Drawing; // pull in GDI+

namespace PaintDotNet.WinForms
{
    public static class ResourcesServiceExtensions
    {
        public static Bitmap GetBitmap(this IResourcesService resources, string streamID)
        {
            return new Bitmap(resources.GetBinaryStream(streamID));
        }

        // similarly for GetIcon, GetCursor, etc.
    }
}

… elsewhere in the code …

menuItem.Image = Resources.GetBitmap("Icons.MenuFileExitIcon.png");
    // Resources is a local property that gets the IResourcesService assigned to us

I could have multiple implementations of IResourcesService. For example, I could have the "normal" implementation that pulls from the local file system, then a test version that does all sorts of fakery, and then maybe experiment with one that loads all my resources via HTTP GET. But, I only ever need one implementation of GetBitmap() because it is just a helper method sitting on top of GetBinaryStream().

But wait, there’s more!

GetBitmap() returns a reference to a System.Drawing.Bitmap object. You generally only care about this type if you’re writing a WinForms application (which I am doing). Or, put another way, you wouldn’t want an object of this type if you were writing a WPF application. You’d want a BitmapSource or something. I am not writing a WPF version of Paint.NET v4, but one of my goals is to have the ability to write one. This is where the "separation of UI and logic" comes into play from my previous post. I refer to the WinForms UI as the shell. The "business logic" portion of the code base is referred to as the application (app for short). You could potentially have a WPF shell, or a command-line shell. Or you could write your own UI toolkit that P/Invokes straight to the Win32 API and bypasses WinForms completely (I believe the latest Zune UI does this).

So, if we wanted a WPF shell for Paint.NET, we could still use the same interface and implementation for IResourcesService. No changes needed anywhere. Why should the resource loader care about what UI you’re using? Its job is to give you strings and binary streams. It’s your job to parse them. It shouldn’t need a reference to the likes of System.Drawing.dll or PresentationCore.dll.

Thus, we’d probably find the following extension method setup useful in our hypothetical WPF shell:

using System.Windows.Media.Imaging;
namespace PaintDotNet.Wpf
{
    public static class ResourcesServiceExtensions
    {
        public static BitmapSource GetBitmapSource(this IResourcesService resources, string streamID)
        {
            return …; // not sure what code goes here exactly 🙂
        }
    }
}

The WPF-based shell would never pull in the PaintDotNet.WinForms namespace, and would instead use the PaintDotNet.Wpf namespace. They’d almost certainly be in separate DLL’s. So these two static extension classes will never collide, even if they have similarly named methods.

Using extension methods this way is probably preferable to "interface inheritance" for adding utility methods. For example, now I don’t need to declare a IWinFormsResourceService that derives from IResourcesService. I can avoid putting all the utility functionality into the base interface which could cause headaches.

As another example of only implementing "strictly orthogonal functionality", consider the case of the System.Windows.Threading.Dispatcher class and its CheckAccesss() and VerifyAccess() methods. The latter basically calls the former and converts true/false into return/throw. It could be done as an extension method. In fact, I have my own IDispatcher interface in Paint.NET v4, and this is exactly what I do. For sections of my code that are P/Invoke heavy, I’ve found it useful to have a SizeOf() method attached to any struct, as opposed to calling Marshal.SizeOf(Type). Less keystrokes, and I think it improves readability.

Advertisements