Welcome to Joe E. Bennett Sign in | Join | Help

Intercept Something

I've been working with the Unity DI framework lately.  The guys at P&P have created a piece of work you really should get to know.  Unity encourages developing highly cohesive and loosely coupled modules for use in your application.  That's great, but there are some cross-cutting concerns that tend to muddy up our code.  For example, logging various kinds of information at runtime is a common task.  Sometimes it seems as if we have as much logging code in our applications as we have code that actually does what our application was intended to do.  Including that logging code just kicks our cohesiveness out the door.  We are no longer focused on just one task.  We now are focused on one task and logging.  It can make a method hard to understand just because the logging code tends to mask what the method is actually doing.  Unity provides a solution to that problem.

The Interception Extension for Unity provides the capability to intercept a method call, do something before the call and after the call.  That sounds like it's ideal for logging doesn't it?  As it turns out, it actually works very well for handling that kind of cross-cutting concern without muddying up our code.  An easy way (but not the only way) to accomplish interception is to create a new LogAttribute and override its CreateHandler method.

Make sure you have references to Microsoft.Practices.ObjectBuilder2, Microsoft.Practices.Unity, and Microsoft.Practices.Unity.Interception in your project and a using Microsoft.Practices.Unity.Interception directive at the top of your source file.

public class LogAttribute : HandlerAttribute

{

    public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)

    {

        return new LogCallHandler();

    }

}

Now create the LogCallHandler class like this:

public class LogCallHandler : ICallHandler

{

    private int order;

    public LogCallHandler() : this(0) {}

    public LogCallHandler(int order)

    {

        Order = order;

    }

    public int Order

    {

        get { return order; }

        set { order = value; }

    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)

    {

        ILogger logger = container.Resolve<ILogger>();    // get your logger

        logger.Write("Precall logging");    // log whatever you want before the call

        var result = getNext().Invoke(input, getNext);  // this invokes the method you called

        logger.Write("Postcall logging");    // log whatever you want after the call

        return result;

    }

}

Now, add the Interception Extension to the container and configure it to use the InterfaceInterceptor.

container.AddNewExtension<Interception>();

container.Configure<Interception>().SetInterceptorFor<IMessenger>(new InterfaceInterceptor());

You have the container configured so that any class that implements the IMessenger interface can have its methods intercepted.  To wire everything together, use the LogAttribute  you created on the methods of IMessenger you want logged.  In the concrete class, when you call a method of the IMessenger interface that has the LogAttribute on it, it will be intercepted and the Invoke method above will be called instead.  The information you wanted logged before the call is logged, then the call is made to the method you called, then the information you wanted logged after the call is logged.

Enjoy!  More information is available on using Interception with Unity.

Published Tuesday, March 17, 2009 9:18 AM by jbennett
Filed under: ,

Comments

No Comments
Anonymous comments are disabled