Interception with Unity
I've already written about this here but this is such a obscure topic that it really doesn't hurt with some more examples. In this example we have a bookstore with two repositories defined as below.
public interface IAuthorRepository { IList<Author> GetAuthorsForBook(string isbn); }
I would like to measure how long these calls take, but I don't want to change the implementation. This can be done with AOP and interception.
ICallHandler
We create a class that implements ICallHandler. This is the code that will intercept the calls.
watch.Start();
var result = getNext()(input, getNext);
watch.Stop();
Debug.WriteLine("End: {0} ({1} ms, {2} ticks)", input.MethodBase.Name, watch.ElapsedMilliseconds, watch.ElapsedTicks);
return result;
}
public int Order { get; set; }
}
The strange call getNext()(input, getNext)
is the actual call to the method that is intercepted. The Order property controls the inner order of interceptions.
IMatchingRule
Interception is done by putting a proxy class on top of the class/interface that should be intercepted. But how do we control that only some methods on that class/interface should be interrupted? We implement a IMatchingRule.
This matching rule always returns true, which means that we want to intercept everything on that class/interface. Otherwise we could use the MethodBase argument to return true or false.
Container configuration
Last, but not least, we have to tell the Unity container to intercept these interfaces with out MeasureLatencyCallHandler filtering the methods with our AnyMatchingRule.
container.RegisterType<IMatchingRule, AnyMatchingRule>("AnyMatchingRule"); container.RegisterType<ICallHandler, MeasureLatencyCallHandler>("MeasureLatencyCallHandler");
container.Configure<Interception>().AddPolicy("TracePolicy") .AddMatchingRule("AnyMatchingRule") .AddCallHandler("MeasureLatencyCallHandler");
container.Configure<Interception>().SetInterceptorFor(typeof(IBookRepository), new InterfaceInterceptor()); container.Configure<Interception>().SetInterceptorFor(typeof(IAuthorRepository), new InterfaceInterceptor());
That's it! You will find the source here, or you can download as a zip archive.