Posterous theme by Cory Watilo

Filed under: Investigation

A Survey of Javascript Thought

Media_httpstaticjscon_qefea
Frameworks Knowledge People, Podasts, and News Tools Careers

Windows Forms Eventing: Generic Pub/Sub

In my last post, I covered how you can implement a publish/subscribe system for sending events between components of your Windows Forms application. Using this model, it is easy to create separate components that don’t rely on each other’s implementation details in order to provide a consistent experience for the user. A button on the toolbar can be disabled by an action on the data entry screen…without hard references between the two.

However, the implementation from last time required a new aggregator and set of interfaces for each message type that needed to be passed around. Let’s fix that with generics.

Listener Interface

First we replace the IEventReciever interface from last time with a generic IListener interface that uses a generic type for the message object.

public interface IListener<T>
{
void Handle(T message);
}
All your subscribers now implement an IListener<Message> for each message type they can handle. (This is great because one class can listen for multiple types of messages!)

Event Aggregator Interface

Similarly, the Event Aggregator needs a generics reset. Notice that the Add and Remove methods now accept any old object.

public interface IEventAggregator
{
void SendMessage<T>(T message);
void AddListener(object listener);
void RemoveListener(object listener);
}

Event Aggregator

public class EventAggregator
: IEventAggregator
{
private readonly List<object>
listeners = new List<object>();

#region IEventAggregator Members

public void SendMessage<T>(T
message)
{
listeners.CallOnEach<IListener<T>>(x => { x.Handle(message); });
}

public void AddListener(object listener)
{
if (listeners.Contains(listener)) return;
listeners.Add(listener);
}

public void RemoveListener(object listener)
{
listeners.Remove(listener);
}

#endregion

}

Not much new here….except for that CallOnEach method. Where did that come from?

Extension Methods

We need to add a few utility methods to the IEnumerables so that we can send our messages:

public static void CallOnEach<T>(this IEnumerable
enumerable, Action<T> action) where T : class

{
foreach (object o in enumerable)
{
o.CallOn(action);
}
}

public static void CallOn<T>(this object target,
Action<T> action) where T : class

{
var subject = target as T;
if (subject != null)
{
action(subject);
}
}

Put those in a likely static class somewhere.

Are we there yet?

This Event Aggregator is getting powerful. We should kill it before it develops language skills.

With the code we have so far, we can easily create a new message in the system without modifying the aggregator code. I like adding the methods as child classes of their receivers (when they are receiver-specific).

There is, however, still a problem. In the type of application that needs this eventing system, you are likely going to need to do some background threading to keep the UI responsive. The Event Aggregator we have doesn’t do anything to keep itself or the rest of the application synchronized.

What happens when a background thread sends a message that the receiver needs to act on by talking to the UI thread? Do you write a bunch of Invoke() code everywhere?

As it turns out, there is a better way. And my next post will show you how to upgrade your EventAggregator to be the thread master!

Windows Forms Eventing: Adding Pub/Sub

In my last post, I described the creeping problem I’ve been having with wiring my large Windows Forms application up with EventHandler delegates. In short, the design becomes brittle—it’s hard to write and hard to change. Luckily, the solution is an easy one: Publish/Subscribe.

The Event Aggregator is a singleton. You can either manage this yourself, or you can have your Inversion of Control container do it for you. When an Event Receiver is created, it registers itself with the Event Aggregator, which stores a reference to the receiver. When a Event Sender sends a message to the Event Aggregator, the aggregator loops through all the registered receivers and calls a method on them to handle the event. This is facilitated by having the receivers implementing an interface. Here’s a simple implementation:

public class EventMessage
{
public string MessageText
{ get; set; }
}

public interface IEventReceiver
{
void Handle(EventMessage message);
}

public interface IEventAggregator
{
void SendMessage(EventMessage message);
void AddReceiver(IEventReceiver receiver);
void RemoveReceiver(IEventReceiver receiver);
}

public class EventAggregator
: IEventAggregator
{
private readonly List<IEventReceiver>
receivers = new List<IEventReceiver>();

#region IEventAggregator Members
public void SendMessage(EventMessage
message)
{
receivers.ForEach(r => r.Handle(message));
}

public void AddReceiver(IEventReceiver
receiver)
{
if (receivers.Contains(receiver)) return;
receivers.Add(receiver);
}

public void RemoveReceiver(IEventReceiver
receiver)
{
receivers.Remove(receiver);
}
#endregion

}

public class EventReceiver
: IEventReceiver
{
public EventReceiver(IEventAggregator aggregator)
{
aggregator.AddReceiver(this);
}

#region IEventReceiver Members
public void Handle(EventMessage
message)
{
Console.WriteLine(message.MessageText);
}
#endregion

}

public class EventSender
{
private IEventAggregator aggregator;

public EventSender(IEventAggregator aggregator)
{
this.aggregator = aggregator;
}

public void SendErrorMessage(string message)
{
aggregator.SendMessage(new EventMessage { MessageText
= message });
}
}

This is a big improvement over manual event wiring through an application. No longer do the targets of a message need to know (have references to) the senders of the message in order to make the connection. You can add a new target (receiver) without changing the code of the sender. You can add a new sender without changing the code of the receivers. And you don’t have to manually map things out in some sort of registry class. This is simple easy and it will work.

It’s always something with you, isn’t it?

Ok. I like it. I’m happy. But how many of these things am I going to have floating around? It seems like a lot of code to write to hand one type of event between some components. I’m going to have to hire some Indian outsourcing company to write all of these singleton aggregators.

This sounds like a job for generics! My next post will rewrite the Event Aggregator so that a single aggregator can handle every message your application has.

Windows Forms Eventing: The Problem

Anxiety. This is a feeling I’ve been learning to recognize as a SIGN when I’m coding. The feeling you get when the camera gets really close on the face of the pretty girl as she walks around the empty, and silent, house. Is she going to turn around suddenly and be given flowers? Or is the disemboweling only moments away. You don’t know, but you’re cringing either way.

I’ve felt this in the past about data access layers. This is the feeling I’ve been accumulating around my Windows Forms application lately. I don’t want to code. I’m afraid to code. It’s going to be painful. I’m not sure what’s going to go wrong. But something will, and I’ll be sucked into the unproductive death pit.

Having spent a bit of time feeling around the problem, I’m pretty sure what I don’t like is having to deal with events. Let’s take a look at the reason why:

Windows forms makes things easy.

Click click click! I have a button and I have an event linked to it. Amazingly productive. My app will be running in no time.

Event Handlers are teh awesome.

It’s so easy to link an action to an event handler. Well. It’s pretty easy. It’s very easy within one class. Not so bad if you’ve got a reference to the object that contains the event handler. A little bit of encapsulation makes it harder. Chained event handlers can fix that though……

All is happy with one form per task.

This form is easy. Add a few buttons and it’s great. If you’re prepared to make your application out of a bunch of forms that the user will work with one-by-one, there’s no problem.

However….sovereign apps don’t look like that.

If the user is going to be in one application all day long, it will have to provide easy access to a number of different types of functionality. The application can’t consolidate all of the interface elements required for a single task into a single place. Rather there’s a spaghetti monster of functionality, reaching it’s noodley appendages everywhere.

Events flying every which way, and everything needs a hard reference to everything else.

Can you actually wire all this up with EventHandler references? Sure. Of course you can. However, you end with a lot of tightly coupled code that is a real mess to create and to maintain.

Hope. The eternal struggle.

A application shell is a complicated beast. But problems have solutions. In my next post, I’ll show how you can integrate all these separate components without strangling yourself in wiring.

The Mystery of the Missing Permission

While writing Unit Tests for my membership provider code, I tried adding a permission I had defined on one test user to a different test user. I was completely freaked out, since user1 suddenly no longer had that permission.

What kind of witchery is this? Does Collection<T>.Add() remove items from the source collection?

No. It doesn't. I tried it all with simple collections. List<string>.Add() doesn't have this effect. So what's going on?

The problem has to be in my persistence layer. My User and Permissions objects are provided by LLBLGen. So it's gotta be something in there. (A light dawns). I look back at my table definitions. Sure enough, a permission as a m:1 relationship with it's user. A permission entity can't belong to more than one user. And LLBLGen is smart enough that when I take the object in the graph and add it to a different user, it not only updates the relationship(FK), but removes it from the original object.

But how do I get the result I wanted? A simple duplication of an existing permission? I adapted the deep copy method I found over on Stack Overflow into a general extension method and used it to dupe the permission as I added it. Clean copy in the object graph=>no changes to the relationship(FK)=>success.

public static class DeepCloneExtension { public static T DeepClone<T>(this T obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T)formatter.Deserialize(ms); } } }