MessengerAdapter<TEnum>

Jun 6, 2010 at 11:01 PM
Edited Jun 6, 2010 at 11:05 PM
I built a very simple "adapter class" that allows you to use enum values instead of a strings when working with Messenger objects. Thought I'd pass it along in case anyone might find it useful.

Here's the class:

    public class MessengerAdapter<TEnum>
    {
        private readonly Messenger _messenger = new Messenger();

        public void NotifyColleagues(TEnum messageKey)
        {
            _messenger.NotifyColleagues(messageKey.ToString());
        }

        public void NotifyColleagues(TEnum messageKey, object value)
        {
            _messenger.NotifyColleagues(messageKey.ToString(), value);
        }

        public void Register(TEnum messageKey, Action callback)
        {
            _messenger.Register(messageKey.ToString(), callback);
        }

        public void Register<T>(TEnum messageKey, Action<T> callback)
        {
            _messenger.Register<T>(messageKey.ToString(), callback);
        }
    }

--------------------------------------------

Example usage:

----- messenger instantiation (in App.xaml.cs) -----

        private readonly static MessengerAdapter<MessengerCommands> _messenger = new MessengerAdapter<MessengerCommands>();

        internal static MessengerAdapter<MessengerCommands> Messenger
        {
            get { return _messenger; }
        }

----- enum declaration -----

    public enum MessengerCommands
    {
        MapClicked,
        SelectedCityChanged,
        SelectedRouteChanged
    }

----- NotifyColleagues -----

    public Route SelectedRoute
    {
        get { return _selectedRoute; }
        set
        {
             if (value == _selectedRoute) return;
            _selectedRoute = value;
            RaisePropertyChanged("SelectedRoute");
            App.Messenger.NotifyColleagues(MessengerCommands.SelectedRouteChanged, _selectedRoute);
        }
    }

----- Register -----

    App.Messenger.Register<Route>(
            MessengerCommands.SelectedRouteChanged,
            route => FilterWaypoints(route));

--------------------------------------------

Some advantages I've noticed of using this adapter versus the original Messenger:

1. If you mistype the message key, you will receive a compile-time error, so you can immediate catch and easily correct any mistakes.
2. By requiring that you specify the enum you'd like to use for a particular MessengerAdapter, the available keys for a particular messenger are enforced.
3. You can use Visual Studio's "Find All References" feature to find all the places in your code where a particular message key was used (useful for determining if a message has both a sender and a receiver).
4. Admittedly, you could always create a class with a bunch of string constants, but I would argue that enums are a more elegant solution for several reasons:
   - With constants, you quickly realize the value of the constant has no meaning whatsoever. It just needs to be unique (in my case, it was always the same as the name of the constant). So, why not use an enum, which handles the assignment of unique values to names automatically?
   - Enums, because of their familiarity, are a better way to express the intent of your code than a class with string constants.
   - Using enums requires less typing.
   - Enums are easier to maintain. Namely, if you change the name of one of your message keys, you don't have to also change the corresponding string value (assuming your string values have some relationship to your names).