So my final piece of functionality for the week in Project Resistance was to add key handling to the code base. The idea is that if you’re running on a non-touch device (or for some reason want to use the D-Pad on a touch device) then you need some ability to “select” a resistance band to change. I plumbed through events from the Form down to the ResistorController, and back up to the View so now you can move left or right to select a resistance band and then up or down will cycle the band just like a gesture will. Of course there’s nothing yet to *visually* show you what band is selected, but the code is in place for it.
What’s most interesting about the way this works is that I’m not using the standard old EventHandler subscription mechanism in code. Instead I’m using a pattern called “event aggregation.” It’s a bit odd, but I couldn’t find a reasonable definition online of exactly what event aggregation is, so instead of a link, I’ll actually have to provide a bit more information.
Event aggregation is the ability of a framework to automatically collect up (or aggregate) event information and wire publishers to subscribers. The OpenNETCF.IoC framework, which Project Resistance is using for Dependency Injection and as well as the UI framework, also provides Event Aggregation through simple Attributes. Let’s look at this key-handling as an example.
In the normal old-school event handling way of thinking, if the ResistorController wanted to get events when a KeyDown happened on the Form, the controller would need a reference to the Form so it could do a form.KeyDown += new KeyEventHandler(Foo). The problem with this is that to do this, the Controller now has to know about the Form, meaning that they get coupled together. That’s bad from a maintenance and extensibilty standpoint, and it really sucks from a test standpoint.
Sure, I could interface the Form and then pass an interface reference in, but still, why does the Controller need to know anything about the Form? Really it just wants to know when some other component wants to change the currently selected band or change the value of the selected band.
Well this is a classic case of where Event Aggregation rocks. In the OpenNETCF.IoC framework, we simply need to know the string name of the event (which is stored in a global constant so everyone can use it).
The Form “publishes” the event with a simple attribute like this:
public event KeyEventHandler DPadKeyPressed;
The anything that wants to receive the event simply uses an attribute to subscribe. This is what it looks like in the ResistorController:
public void DPadHandler(object sender, KeyEventArgs e)
By the nature of the fact that these objects were inserted into one of the IoC framework’s DI container collections, the two automagigically get paired up. No references get passed around, no interfaces get unnecessarily polluted, and out objects stay nicely decoupled. All that is required is that both attributes use the same string name for the event and that the handler method signature matches the expected publisher’s delegate.