Roll Your Own Simple Message Bus / Event Aggregator

by Brent 13. April 2010 03:43

I was recently working on a project that had a need for some sort of centralized messaging system.  After doing some research into the matter, I decided to move forward with the Event Aggregator from the Prism team.  Prism’s Event Aggregator worked fine, but there were a few things about it that I found cumbersome.  While preparing for a presentation I gave recently, called “WPF with MVVM: From the Trenches,” I began to think about what it would take to create my own event aggregator that would smooth over some of the bumps.

First up, lets talk about the name, “Event Aggregator.”  During the course of our project, we used the event aggregator to publish data (or messages) in addition to events.  During a discussion about the event aggregator, Jason Bock pointed out that it is really more of a “Message Bus” than an “Event Aggregator.”  I agree.  So, for the remainder of this post, I will refer to it as a “Message Bus.”

The next bump that I wanted to smooth over was the fact that, with Prism, we had to create both an Event class which derived from CompositePresentationEvent<T> and an EventArgs class for every message we wanted to publish.  With Prism, I wrote an extension method, called GetEventViaArgs<T>(), which would get the CompositePresentationEvent based on the type of the args.  That eliminated the need for an explicit Event class, but that also made me question the need for an Event at all.  What if the message type was all that we needed for subscribing and publishing?  Eliminating the need for an Event would simplify testing as well because we wouldn’t have to mock out both getting the event and subscribing/publishing the message, which so happens to be another bump that I wanted to smooth over.

A Starting Point

So, lets take a look at the method signatures that I had in mind.  A Message Bus should provide functionality to Subscribe to a message, Unsubscribe from a message and Publish a message.

// Subscribe to messages of type SearchMessage, providing
// HandleSearch as the callback method.
messsageBus.Subscribe<SearchMessage>(HandleSearch);

// Publish a message of type SearchMessage.
var search = new SearchMessage(keywords);
messageBus.Publish<SearchMessage>(search);

// OR publish a message without explicitly defining
// the type.
messageBus.Publish(search);

// Unsubscribe from messages of type SearchMessage.
messageBus.Unsubscribe<SearchMessage>(HandleSearch);

This looks straight-forward enough.  Whatever implementation I come up with, it should leverage generics to make sure all interested parties are notified of messages they care about.  The method signature I would like to see for the callbacks would be something like this:

public void HandleSearch(SearchMessage message)
{
	// Do something with the message.
}

Since I am a big fan of dependency injection and inversion of control, I wanted to define an interface, called IMessageBus, to be used instead of a concrete implementation.  Keeping in mind how I wanted to use this bad boy, here is the interface I came up with:

public interface IMessageBus
{
	void Subscribe<TMessage>(Action<TMessage> handler);
	void Unsubscribe<TMessage>(Action<TMessage> handler);
	void Publish<TMessage>(TMessage message);
	void Publish(Object message);
}

Let me break this down a bit…  TMessage is the Type of the message to be sent.  Action<TMessage> is a way for me to take, as a parameter, a method which has a void return value and takes a parameter of type TMessage.  Also note that TMessage is just a class that contains whatever data we need to convey the message.

So far, so good.  We now have a contract in place for our message bus.  Next up is implementation.

Making It Happen

First, we need a data structure that will have some sort of key/value association.  The key will be the Type of TMessage and the value will be the collection of Action<TMessage> which will be called when a message of type TMessage is published.  Since I plan to use generics at the method level, I decided to use Object in place of Action<TMessage>, then cast it before using it.  So, here is our MessageBus class so far:

public sealed class MessageBus : IMessageBus
{
	private Dictionary<Type, List<Object>> _Subscribers = 
		new Dictionary<Type, List<Object>>();
}

Now that we have a data structure in place to keep track of subscribers, time to implement the Subscribe method.  Now, when a new subscriber is added, we need to first find out if there is already a subscriber list for that message type.  If there is, use it.  Otherwise, create a new one.

public void Subscribe<TMessage>(Action<TMessage> handler)
{
	if (_Subscribers.ContainsKey(typeof(TMessage)))
	{
		var handlers = _Subscribers[typeof(TMessage)];
		handlers.Add(handler);
	}
	else
	{
		var handlers = new List<Object>();
		handlers.Add(handler);
		_Subscribers[typeof(TMessage)] = handlers;
	}
}

Next up is Unsubscribe.  When a subscriber makes a call to Unsubscribe, we need to make sure they are actually a subscriber in the first place and remove them if they are.  Also, if they are the last subscriber, we can go ahead and remove the subscriber list for that message type.

public void Unsubscribe<TMessage>(Action<TMessage> handler)
{
	if (_Subscribers.ContainsKey(typeof(TMessage)))
	{
		var handlers = _Subscribers[typeof(TMessage)];
		handlers.Remove(handler);

		if (handlers.Count == 0)
		{
			_Subscribers.Remove(typeof(TMessage));
		}
	}
}

Almost there.  Now we just need to be able to Publish.  As you probably noticed above, I thought it would be nice to both explicitly define what type of message to publish and let the message type be determined dynamically.  For either case, we need to get the list of subscribers for the type of message being published and invoke each of their callback methods with the message as a parameter.  First up is the explicitly define flavor:

public void Publish<TMessage>(TMessage message)
{
	if (_Subscribers.ContainsKey(typeof(TMessage)))
	{
		var handlers = _Subscribers[typeof(TMessage)];
		foreach (Action<TMessage> handler in handlers)
		{
			handler.Invoke(message);
		}
	}
}

Pretty straight-forward here too.  If there are subscribers for that message type, iterate over them (casting them in the process) and invoke them.

The dynamic version of Publish is a little more involved, only because we have to use reflection in place of generics due to the dynamic aspect:

public void Publish(Object message)
{
	var messageType = message.GetType();
	if (_Subscribers.ContainsKey(messageType))
	{
		var handlers = _Subscribers[messageType];
		foreach (var handler in handlers)
		{
			var actionType = handler.GetType();
			var invoke = actionType.GetMethod("Invoke", new Type[] { messageType });
			invoke.Invoke(handler, new Object[] { message });
		}
	}
}

This one is essentially doing the same thing as the other Publish method.  If there are subscribers for that message type, iterate over them (finding their Invoke method in the process) and invoke them.  Don’t be confused by the two different Invokes that you see…  The first Invoke is the name of the method on the Action type and the second Invoke is what reflection uses to execute a method.

There we have it!  A simple message bus that is easy to use.  But how about testing with it?  Since testing was one of the bumps I wanted to smooth over, how did we do?  Let’s find out!

Testing Our Shiny New Message Bus

I use RhinoMocks, so here is how I would verify that some code is publishing the correct message:

SearchMessage searchMessage = null;
var messageBus = MockRepository.GenerateStub<IMessageBus>();
messageBus.Stub(bus => bus.Publish<SearchMessage>(Arg<SearchMessage>.Is.Anything))
	.WhenCalled(inv => searchMessage = inv.Arguments[0] as SearchMessage);

I generate a stub for IMessageBus which will set my local searchMessage variable to the actual SearchMessage that is published.  I then could use searchMessage to verify that the message that is published has the correct data.

As an alternative, if all I wanted to do was verify that Publish was called on my Message Bus, I could do the following:

SearchMessage searchMessage = null;
var messageBus = MockRepository.GenerateMock<IMessageBus>();
messageBus.Expect(bus => bus.Publish<SearchMessage>(Arg<SearchMessage>.Is.Anything));

The key changes here are that I am using a Mock instead of a Stub and I am setting up an expectation.  That way I can verify that Publish was called without caring about the details:

messageBus.VerifyAllExpectations();

Testing for messages being published is now much cleaner with our new MessageBus than it would be with Prism’s Event Aggregator.  But what about testing the handling of these messages that get published?  Well, the best way that I could come up with for that is the same way I did it with Prism’s Event Aggregator, which is to use the concrete implementation of the MessageBus and actually subscribe and publish with it in the unit test.  Oh well, at least we were able to clean up some of the testing aspect!

Conclusion

So, here we are at the end.  My goal here was to show that it isn’t all that difficult to implement your own message bus system or, at the very least, show the general concept behind how it works.  I hope that this has been useful.  If you want play with the code that we have written, as well as the tests that I wrote to beat on it a little, you can download the source here:

WPF with MVVM: From the Trenches - Presentation Materials

by Brent 10. April 2010 14:37

If you were at my talk at Twin Cities Code Camp 8, I hope you found it useful.  I realize that it was a lot of information presented fairly quickly, so I am providing my slide deck along with the entire demo solution (including unit tests) for you to check out at your own pace.

Slide Deck

Demo Application: Movies.zip

Using WPF’s ContentControl to Switch Between Editable and Read-Only Mode

by Brent 4. March 2010 15:59

I’ve been working with WPF a lot lately for a client project and I’ve learned some pretty cool tricks along the way.  I am planning to do a bunch of posts describing many of these tricks in the near future.  The first cool trick I will be talking about is how to make a control that switches between editable mode and read-only mode using only XAML, kind of.

I say ‘kind of’ because we will have some code to make it happen, but not in the code-behind.  Rather than use a code-behind, we will be leveraging the Model-View-ViewModel (MVVM) design pattern to keep our code separate and testable.

Let’s dive right into the code by taking a look at the view model.  Since we will be leveraging WPF’s awesome data binding, we need to prepare the view model to allow WPF to keep track of property changes.  To do this, our view model will implement INotifyPropertyChanged.  Doing so will allow the WPF binding engine to listen for changes and update the view accordingly.

public class SampleViewModel : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    private void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            var args = new PropertyChangedEventArgs(propertyName);
            PropertyChanged(this, args);
        }
    }
}

You’ll notice that I added a method called NotifyPropertyChanged.  This is just to simplify the process of raising the event from the property setters.

Next up we will set up the properties that the view will be binding to.  Our example is very simple, so there will only be two properties in the view model: IsReadOnly and Name.

private Boolean _IsReadOnly;
public Boolean IsReadOnly
{
    get { return _IsReadOnly; }
    set
    {
        _IsReadOnly = value;
        NotifyPropertyChanged("IsReadOnly");
    }
}

private String _Name = "Bob Lablaw";
public String Name
{
    get { return _Name; }
    set
    {
        _Name = value;
        NotifyPropertyChanged("Name");
    }
}

Notice that both of the setters make a call to NotifyPropertyChanged, giving the name of the respective property.  That is what will signal the binding engine to update anything that is bound to one of those two properties.

That’s it for the view model.  We’re keeping things simple.  Let’s move on to the view itself.  First things first, we need to set up the view model as the DataContext.

<Window x:Class="DataTemplatesTriggers.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:DataTemplatesTriggers.ViewModels"
    Title="Window1" Height="300" Width="300">
    <Window.DataContext>
        <vm:SampleViewModel />
    </Window.DataContext>
</Window>

Next up we are going to set up some the style for the ContentControl.

<Window.Resources>
    <Style x:Key="NameStyle" TargetType="ContentControl">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsReadOnly}" Value="True">
                <Setter Property="ContentControl.Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Grid>
                                <Label Content="{Binding Name}" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsReadOnly}" Value="False">
                <Setter Property="ContentControl.Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Grid>
                                <TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Now, this is where the magic happens.  You’ll see that we have a style here with two DataTriggers.  Both of the DataTriggers bind to the IsReadOnly property of our view model.  One of the DataTriggers handles when IsReadOnly is True and the other handles when IsReadOnly is False.

If IsReadOnly is True, we set the Template to a Grid with a static Label.  The Label is bound to the Name property.

If IsReadOnly is False, we set the Template to a Grid with a TextBox.  The TextBox also binds to the Name property and sets UpdateSourceTrigger=PropertyChanged.  The reason for this is that the binding would normally wait to trigger an update to the property until it loses focus.  Setting UpdateSourceTrigger=PropertyChanged will trigger the update with every key press.

The only missing piece to this puzzle is to place the actual ContentControl.

<Grid Margin="10">
    <StackPanel Orientation="Vertical">
        <CheckBox Content="Read Only" IsChecked="{Binding IsReadOnly}" />
        <ContentControl Style="{StaticResource NameStyle}" />
    </StackPanel>
</Grid>

To use the style we created above, we simply need to bind the Style of the ContentControl to the Style with the Key Name.  You’ll also notice that I have placed a CheckBox in there as well, giving a way to test that the whole operation works.

So, that pretty much wraps it up.  We now have a control that completely changes it’s look based on only a boolean value.  Although this example is quite simple, this approach can be applied to more complex situations.  You can take the solution at the end of the post and poke around a little.

Hopefully this has been helpful!  Have fun with it!

Generic Command Binding with WPF and Prism

by Brent 15. December 2009 16:17

I’ve been working a lot with WPF lately for a client project. I really enjoy working with WPF and this project is giving me the chance to really flex my WPF skillz. To make our app as testable as possible, I made the push to move to an MVVM architecture. I’m not going to discuss the details of MVVM, but I will say that is a pretty cool way to keep your functionality independent from your presentation.

To really leverage MVVM, we needed a way bind events to our view models. Luckily, Prism offers functionality that does just that. They take the concept of Command Binding and elaborate on it allowing you to bind events to commands on your view model. Command binding with Prism is reasonably easy, but it does require the creation of several classes for every event that you want to bind to. As it turns out, most of the code required for those classes is repetitive and can be generalized to work with all events on all controls.  In this post I will show you the classes I created, based on the blueprints laid out by the Prism team, which allows such binding to happen.

First up, let’s take a look at the class that actually executes the command, CommandBehaviorBinder:

/// <summary>
/// Behavior that allows controls that derive from <see cref="Control"/>
/// to hook up with <see cref="System.Windows.Input.ICommand"/> objects.
/// </summary>
/// <typeparam name="C">
/// The type of <see cref="Control"/> to hook up.
/// </typeparam>
public class CommandBehaviorBinder<C>
: CommandBehaviorBase<C> where C : Control 
{
	/// <summary>
	/// Initializes a new instance of the <see cref="CommandBehaviorBinder"/> class.
	/// </summary>
	/// <param name="control">The control.</param>
	public CommandBehaviorBinder(C control)
		: base(control)
	{
	}

	/// <summary>
	/// Executes the command.
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	public void Execute(Object sender, EventArgs e)
	{
		ExecuteCommand();
	}
}

A couple of things to take note of here:

1. CommandBehaviorBase is a class (provided by Prism) which associates an ICommand, the command’s parameter (if any) and the target object which the command is attached.

2. The generic type associated with CommandBehaviorBinder must be of type Control.

3. The Execute method just calls the ExecuteCommand method provided by CommandBehaviorBase.

Next up is the class which contains the actual Dependency Properties for a Command and an optional CommandParameter. This class is called Commander:

/// <summary>
/// Class that holds all Dependency Properties and Shared methods to allow an
/// event of a DependencyObject class to be attached to a Command.
/// </summary> public class Commander { private static readonly DependencyProperty EventCommandBehaviorProperty =
DependencyProperty.RegisterAttached( "EventCommandBehavior", typeof(CommandBehaviorBinder<Control>), typeof(Commander), null); /// <summary> /// Command to execute on when the event is fired. /// </summary> public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached( "Command", typeof(ICommand), typeof(Commander), new PropertyMetadata(OnSetCommandCallback)); /// <summary> /// Command parameter to supply on command execution. /// </summary> public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.RegisterAttached( "CommandParameter", typeof(Object), typeof(Commander), new PropertyMetadata(OnSetCommandParameterCallback)); /// <summary> /// Event name to bind command to. /// </summary> public static readonly DependencyProperty EventNameProperty =
DependencyProperty.RegisterAttached( "EventName", typeof(String), typeof(Commander), null); /// <summary> /// Sets the <see cref="ICommand"/> to execute when the event is fired. /// </summary> /// <param name="control">DependencyObject to attach Command.</param> /// <param name="command">Command to attach.</param> public static void SetCommand(Control control, ICommand command) { control.SetValue(CommandProperty, command); } /// <summary> /// Retrieves the <see cref="ICommand"/> attached to the <see cref="Control"/>. /// </summary> /// <param name="control">
/// DependencyObject containing the Command dependency property.
/// </param>
/// <returns>The value of the command attached.</returns> public static ICommand GetCommand(Control control) { return control.GetValue(CommandProperty) as ICommand; } /// <summary> /// Sets the value for the CommandParameter attached property on the provided
/// <see cref="Control"/>.
/// </summary> /// <param name="control">DependencyObject to attach CommandParameter.</param> /// <param name="parameter">Parameter value to attach.</param> public static void SetCommandParamter(Control control, Object parameter) { control.SetValue(CommandParameterProperty, parameter); } /// <summary> /// Gets the value in CommandParameter attached property on the provided
/// <see cref="Control"/>.
/// </summary> /// <param name="control">DependencyObject that has the CommandParameter.</param> /// <returns>The value of the property.</returns> public static Object GetCommandParameter(Control control) { return control.GetValue(CommandParameterProperty); } /// <summary> /// Sets the value for the EventName attached property on the provided <see cref="Control"/>. /// </summary> /// <param name="control">DependencyObject to attach the EventName to.</param> /// <param name="eventName">The name of the event to attach.</param> public static void SetEventName(Control control, String eventName) { control.SetValue(EventNameProperty, eventName); } /// <summary> /// Gets the value in EventName attached property on the provided <see cref="Control"/>. /// </summary> /// <param name="control">The DependencyObject that has the EventName.</param> /// <returns>The value of the property.</returns> public static String GetEventName(Control control) { return control.GetValue(EventNameProperty).ToString(); } private static void OnSetCommandCallback(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e) { var control = dependencyObject as Control; if (control != null) { var behavior = GetOrCreateBehavior(control); behavior.Command = e.NewValue as ICommand; } } private static void OnSetCommandParameterCallback(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e) { var control = dependencyObject as Control; if (control != null) { var behavior = GetOrCreateBehavior(control); behavior.CommandParameter = e.NewValue; } } private static CommandBehaviorBase<Control> GetOrCreateBehavior(Control control) { var behavior = control.GetValue(EventCommandBehaviorProperty)
as CommandBehaviorBase<Control>; ; if (behavior == null) { behavior = CreateCommandBehavior(control,
control.GetValue(EventNameProperty).ToString()); control.SetValue(EventCommandBehaviorProperty, behavior); } return behavior; } private static CommandBehaviorBase<Control> CreateCommandBehavior(
Control control,
String eventName)
{
var type = control.GetType();
var behavior = new CommandBehaviorBinder<Control>(control);
var info = type.GetEvent(eventName);

if (info != null)
{
var methodInfo = behavior.GetType().GetMethod("Execute");
var handler = Delegate.CreateDelegate(
info.EventHandlerType, behavior, methodInfo, true);
info.AddEventHandler(control, handler);
}
else { throw new ArgumentException(String.Format(
"Target object '{0}' doesn't have the event '{1}'.", type.Name, eventName));
}

return behavior;
}
}

It looks like there’s a lot to digest here, but it’s really not so bad. Here are the key things to notice with this class:

1. All the methods are static. This is to allow for binding from XAML.

2. There are three public Dependency Properties: Command, CommandParameter and EventName. These are what we will actually be binding to from XAML.

3. The middle chunk of the class is devoted to getters and setters to allow for setting the properties from XAML.

4. The last method in the class, CreateCommandBehavior, uses reflection on the control to find the event and add an event handler to it.

Now that our infrastructure is set up, we just need to do some set up to get this thing moving. First of all, create your view model with a property for each command you want to bind to (using the type ICommand):

public ICommand MoveRightCommand { get; set; }
public ICommand MoveLeftCommand { get; set; }

Next, set up the callback methods that will be called when the commands are executed:

private void MoveRight(Object data)
{
…
}

private void MoveLeft(Object data)
{
	…
}

Then instantiate the commands in the view model’s constructor, passing the callback methods as parameters:

MoveRightCommand = new DelegateCommand<Object>(MoveRight);
MoveLeftCommand = new DelegateCommand<Object>(MoveLeft);

Your view model is now all set; time to move over to the XAML. First include the namespaces at the root of your view for the view model and the commanding stuff:

xmlns:vm="clr-namespace:CommandingExample.ViewModels"
xmlns:commands="clr-namespace:CommandingExample.Commands"

Then, set your view model as the view’s DataContext:

<Window.DataContext>
	<vm:ViewModel />
</Window.DataContext>

Finally, add the controls and bind the commands on the new view model to the events of choice:

<Button
	Content="&gt;&gt;"
	commands:Commander.Command="{Binding MoveRightCommand}"
	commands:Commander.EventName="Click" />
<Button
	Content="&lt;&lt;"
	commands:Commander.Command="{Binding MoveLeftCommand}"
	commands:Commander.EventName="Click" />

Here we are binding the commands on our view models to the Click events of these buttons. If we had CommandParameters to bind to, we would do so here as well.

Note that Buttons actually have a Command property that can be bound to more easily than this for the click event, but that is the only control that has such a property and it is easy to illustrate what we are trying to accomplish by using the Button as an example.

That’s it!

As with anything, there are pros and cons to this approach. For pros, the biggie is that no more additional classes need to be written to bind to new events. For cons, you lose the type-safety and design-time intellisense that is inherent with the approach shown in the Prism example projects. In my opinion, the pros outweigh the cons.

If you put this to use, let me know how it goes!

If you want to play around with this, here’s a sample project to tinker with:

Sizzlin' with jQuery Presentation Solution

by Brent 10. November 2009 20:00

For those of you that attended my presentation at the Twin Cities Developer's Guild meeting on November 10, 2009, I hope you found it interesting.  As I mentioned at the end of that presentation, I am posting the solution files for you to download and play with.  This is a Visual Studio 2008 solution, using ASP.NET MVC and jQuery.

Enjoy!

jquery_start _finish.zip (7.90 mb)

About Me

Brent Edwards

Senior Consultant - Magenic

Owner - Edwards Digital Technologies LLC

Twitter :: LinkedIn