In my last post, I gave some examples of how we can use the IDisposable interface in conjunction with the using statement to implement an on/off pattern wrapping around some critical region of code, even though there is no “disposable resource” involved.
Problems with using IDisposable
In this post I want to expand on the previous examples to illustrate a more general solution to that problem. In the previous post, all the examples implemented IDisposable directly in order to participate in the using statement. However, there are reasons why you might not wish to have this coupling: –
Having a type implement IDisposable that has nothing to do with reclaiming of resources is somewhat misleading e.g. changing the console colour or the cursor icon. This is not what IDisposable was created for and can lead to confusion.
We may not always want to call the “on” action on construction of the object; perhaps we want to use it in other scenarios.
Compile-time tools such as Code Analysis and Coderush etc. may complain if you do not implement IDisposable in the “proper” way (with the Boolean overload) etc.
There’s a way around this by making a new interface which I call ISwitchable, which is implemented by any classes that we want to use within the Using statement yet don’t want to implement IDisposable on (for the reasons outlined above).
Obviously, when we call “On” we’ll do the “on construction” action, and “off” will do the equivalent of the “Dispose()” call.
So, how do we use ISwitchable within the context of the Using statement? Well, we can’t directly – obviously the using statement only works with IDisposable – so we use the Adapter pattern. This pattern shows how we can “massage” an object implementing one interface into another interface – in our case, from ISwitchable to IDisposable. We therefore create an adapter class which takes in an object that is of type ISwitchable and adapts it to work with IDisposable: –
And here’s a (cut-down) version of the code for the adapter. All it does it delegate calls from the constructor to On, and Dispose to Off: –
Then we use it as follows, with the results below: –
CodeTimer simply starts a Stopwatch on On, and stops it (and outputs the time) when Off is called.
ConsoleColourInverter swaps the foreground and background console colours whenever On and Off are called.
So, we get two of these switchable “behaviours” applied onto our code; they start automatically, and then remove themselves once the using statement goes out of scope (as can be seen by the timer finishing and the console colour resetting itself). We don’t have to worry about exceptions either in the sense that because this is in a using statement, the finally block will automatically call dispose on both DisposableAdapter instances, which in turn delegate to the ISwitchable’s Off() method.
This is kind of reminiscent of aspect-oriented programming i.e. we’re applying a set of behaviours around some code and letting them do the work without us getting involved. Through the use of the Adapter pattern we have completely decoupled ourselves from IDispose, and with some use of generics are able to use these switchable objects within the context of a using statement pretty succinctly.