So, here’s the final part of my Interception / Behaviours / AOP with Unity thread…
I discussed (at length) an example problem space we have in my previous post; I want to give an example solution which provides very good encapsulation to the client code using Interceptors.
Carrying right on then – we already have a layer of indirection from our concrete Service Proxy in the form of the IServiceProxy interface. So, we can use Unity to put a decorator class in between that and the “real” ServiceProxy. This middle class will delegate calls to the concrete service, and add the behaviour that we need.
Here’s the Interceptor class which will provide caching for our reference data methods. Notice it implements the IInterceptionBehaviour interface which Unity relies on:
Most of it is fairly simple: –
A collection of strings which represent method names whose data we will cache. A more robust implementation might be to use expressions instead of strings…
A couple of boiler-plate methods that the IInterceptionBehaviour interface needs but we don’t require.
A few static helper methods to aid readability
The crux of it is the Invoke method. This gets called when ANY method is called (or property is set/got) on the class we are decorating. We can then interrogate it and decide what to do. In our case, we’re checking if the method name exists in our black-list of method names.
If it doesn’t, we pass the call on to the real method.
If it does, and the data is already cached, we return that data instead.
If it’s not yet cached, we call the real method, cache the return value and then return the method data back out.
That’s the behaviour written – now we have to register it with Unity and against our type. Here’s the code that we need to change to have it work from a client perspective: –
The first line is a one-off call to the container to tell it to enable Interception within Unity. The Registration line has two new items added: –
An Interceptor<InterfaceInterceptor> that tells Unity how to implement interceptor (composition vs inheritance as discussed in my previous post)
The Behaviour that you want to implement – in my case, the Caching Behaviour that I have written
That’s it! We don’t change any client code – the cache happens completely transparently to the user of the proxy. When we now request the IServiceProxy, Unity will generate a decorator class for us and use that in front of the real service proxy. And just to prove it, here’s what it looks like at runtime: –
There’s the debugger which shows us Unity’s generated type (and how it stores a private field called target which points to the real object).
And of course there’s the application successfully running!