NServiceBus edge components or filters
I’ve been trying for a while now to figure out how to do edge components in NServiceBus, which is a pattern that is mentioned in the excellent SOA Patterns book which I recently finished. They are similar to action filter attributes in ASP.Net MVC - allowing you to implement cross-cutting concerns by running some code before and after actions.
In my case, the main thing I want to do is write a log entry for every message that comes in and is processed showing how long it took to execute. I tried a number of things:
- PostSharp - very cool, but I think a bit annoying because every developer on the team would have to register a copy and we rotate people in and out of my team. I’ll probably look into this in the future because it seems like a really useful piece of technology.
- Windsor Interceptors - also pretty cool, but unfortunately if you attach an interceptor to a handler class, it changes the type and NSB no longer recognises it as a handler, so ruled that out pretty quickly.
After these two problems I finally stumbled onto the IManageUnitsOfWork interface that comes with NServiceBus and allows you to run an action before and after every handler invocation. To set it up, first implement it:
public class LoggingUnitOfWork : IManageUnitsOfWork
{
public IBus Bus { get; set; }
public void Begin()
{
Console.WriteLine("Before invocation");
}
public void End(Exception ex = null)
{
Console.WriteLine("After invocation");
// use Bus.CurrentMessageContext to get information about the current message being handled
}
}
Then, register it in your container. I use Windsor:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public void Init()
{
var container = new Castle.Windsor.WindsorContainer();
container.Register(
Component.For<IManageUnitsOfWork>()
.ImplementedBy<LoggingUnitOfWork>()
.LifeStyle.Transient.Named("LoggingUnitOfWork")
);
Configure.With()
.CastleWindsorBuilder(container);
}
}
And that’s it. You can use the injected IBus instance to do just about anything. From what I can tell you can register as many implementations of IManageUnitOfWork as you want, and all of them will be executed, so for example if you’re using the built-in NHibernate plugins this won’t stomp all over its unit of work management system.