Thanks for visiting my blog!
While I recognize my original schedule is slipping, let’s continue the ten part Windows Phone 7 architecture discussion. In this sixth part of the article series, I want to discuss messaging in phone applications. If you’ve missed the past parts of the series, you you can visit them here:
- Part 1 (Navigation Framework)
- Part 2 (Pivot and Panorama)
- Part 3 (View Models)
- Part 4 (Client-side Data)
- Part 5 (Tombstoning)
When I say “Messaging”, I don’t mean SMS or IM, but instead I mean smart ways of being able to talk between different parts of the application.
As you build an application in a loosely coupled way (the way that the MVVM pattern and composition patterns help you do), you will find a point where you need X and Y to communicate in some way but creating a strong relationship between them is what you’re trying to avoid. This is no different on the phone than in development in general. The usual solution for this is to use some sort of loosely couple messaging. The two common ones I’ve used in Silverlight are Laurent Bugnion’s MVVM Light framework (which contains a very light Messenger class) and the Microsoft PnP folks’ Prism project (which contains the EventAggregator).
In practice, I find the Messenger class in MVVM Light to be really easy to work with and is my personal choice when I need this functionality. Luckily for us, Laurent has brought this to WP7:
It works via a simple subscription model. When you want to listen for a message, you simply call the Register method like so:
// In App.xaml.cs in this case
Messenger.Default.Register<string>(this, "ShowError", err =>
{
var msg = string.Concat("An error occurred",
Environment.NewLine,
err);
ShowMessage(msg);
});
The Register takes a payload type (so it doesn’t have to be magic strings) as a generic parameter. In addition, it can take a token that both sides know about (in this case its just a magic string called “ShowError” though in practice I would probably create a static class to share them) so that messages sent with this token will be handled by the register. After the token is an Action<T> that accepts the message and can do something with it. The generic parameter of the Action<T> matches the type in the Register call.
From another part of the application you can send a message in a similar way:
// Called from anywhere in the app (its in the VM here)
Messenger.Default.Send<string>("Could not load model", "ShowError");
The generic parameter matches the type in the original Register and also matches the first parameter of the Send call (so, yes you can send a complex object here). The second parameter is the token that the messenger will use to determine who handles the message.
TThis works well because neither side needs explicit knowledge of each other. In addition, the lifetimes are not tied to each other. In other words, if you send a message before registration, no error occurs (but the message isn’t handled). The messages are coupled (by the token) but are loosely coupled.
By introducing messaging into your application, you can simplify communication across your application and keep the components loosely coupled; making your app easier to build and easier still to maintain.