26 November, 2012

Message bus for ASP.NET MVC application

I am working on a modular ASP.NET MVC application, one of the problems is communication among modules. At the beginning, with just 3 - 4 modules, it might seem possible to call methods among modules directly. As the system grows, number of modules increases and dependencies among modules become more complex, such solution become impractical.

I didn't need anything fancy, just a simple publisher/subscriber pattern implementation for the single application, so I decided to write my own 'library'.

Publisher - subscriber pattern

Implementation

The core of the implementation is the MessageBus class. A publisher obtains an instance of the MessageBus (from IoC container), sends a message and the MessageBus distributes the message to appropriate subscribers.

Subscribers need to implement the IMessageSubscriber<TMessage>  interface, so they can process messages of the desired type.

public interface IMessageSubscriber<TMessage> where TMessage : IMessage {
    void Handle(TMessage msg);
}

The actual implementation of MessageBus is pretty simple, the difficult part - managing references to subscribers is done by an IoC container (encapsulated in IDependencyResolver). An IoC container is usually already in place in MVC applications, so why reinvent a wheel ...  

public class MessageBus : IMessageBus {
    IDependencyResolver _resolver;

    public MessageBus(IDependencyResolver resolver) {
        _resolver = resolver;
    }

    public void Send<TMessage>(TMessage message) where TMessage : IMessage {
        var subscribers = _resolver.Resolve<IMessageSubscriber<TMessage>>();
        foreach (var subscriber in subscribers) {
            subscriber.Handle(message);
 }
   }
}

The final piece of the implementation is registering all necessary classes in the IoC container - in this case I used Autofac.

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<MessageBus>().As<IMessageBus>();
builder.RegisterType<DEPENDENCY_RESOLVER>().As<IDependencyResolver>();
builder.RegisterType<SUBSCRIBER>().As<IMessageSubscriber<MESSAGE>>();

To send a message publisher needs to obtain an instance of the MessageBus from the IoC container and than send the message.

bus = container.Resolve<IMessageBus&gt();
SampleMessage msg = new SampleMessage() { Content = message };
bus.Send<SampleMessage>(msg);

And that's it - a simple message bus, that fulfill my requirements in about 20 lines of code. You can download the source code of the MessageBus with a MVC demo project from GitHub

No comments:

Post a Comment