Monday, 1 October 2012

Unity, Interception, AOP...

Though I've been familiar with Dynamic Proxies, Interception and AOP (on a theoretical basis and on some of my "toy projects") since a long while, it was last year the first time I applied some of this on a Production project. As we were using Unity as IoC, we decided to leverage its interception capabilities for some apparently trivial stuff. We succeeded obtaining the functionality that we were seeking for, but a few things seemed a bit unclear to me, something I mainly blamed on our very tight schedule that made me read too fast through the extensive Unity documentation and online samples

So when I recently came across this excellent series [1, 2 and 3] by Dino Esposito, I thought it would be a good idea to look back to my previous experience and clarify this all for future projects

First we should note that AOP and Dependency Injection are quite different things, but in the last times, most IoC containers provide some kind of (basic) AoP support (Spring.Net, Castle Windsor, Unity. This support is mainly limited to intercepting method calls to insert there code related to our logging, validation, security... cross cutting concern.

This method interception is achieved at runtime by means of Proxy Objects, that either point to the intercepted instance (composition) or inherit from the class being intercepted. Well, this is common ground to Spring, Castle and Unity, but there are a few things in Unity that can lead to some confusion:

  • At least for version 2.0, Unity is completely independent from Enterprise Library (the only relation now is that both are developed by the Patterns and Practices guys). If you want to use Unity's (soft) flavor of AOP all you need is adding these 3 assemblies to your project:
    • Microsoft.Practices.ServiceLocation
    • Microsoft.Practices.Unity
    • Microsoft.Practices.UnityInterception
  • Unity mainly avoids the term "Proxy", using the "Interceptor" term instead. We don't have a ProxyGenerator class as we have in Castle, but the Intercept class does just that, creates Proxies (interceptors)
  • When intercepting calls with Unity, we create a chain of IInterceptionBehavior objects, containing the additional logic that we are injecting. Castle's equivalent to these behaviors are called IInterceptor.

Unity provides us with 2 types of Composition based proxies (Instance Interceptor). You already have an instance of an Object and will wrap it with a Proxy (Interceptor in Unity's parlance): InterfaceInterceptor and TransparentProxyInterceptor
and one type of Inheritance based Proxy (Type Interceptor): VirtualMethodInterceptor

We can create and use proxies without need of an IoC container, though for production applications aiming for decoupling and extensibility, it's obvious that we should create them through a Container

I'll write down a few samples, just based on what we needed in that project last year. Let's say you have a Data Source that you want to mock somehow. Mainly, first you want to serialize the Data Entities returned by the real DAOs, and then you want to use those serialized entities instead of querying the real DAO's-DataSource.

So, if we want to inject in our real DAOs an behavior that will serialize those entities they are returning. For this, we can wrap our real Dao in a Proxy object, this will call the real Dao to retrieve the real entities (from a DB for example) and then will serialize those entities before returning them to the caller code, that is fully unaware of this added behavior.

We can create the Proxy ourselves (I'm using a Composition based Proxy, that is, an InterfaceInterceptor)

IUserDao userDao = new DBUserDao();
            IUserDao userDaoProxy = Intercept.ThroughProxy<IUserDao>(userDao,
                new InterfaceInterceptor(), new[] { new SaveResultBehavior() }
            );
            var users = userDaoProxy.GetUsers("Asturies");

Obviously, to decouple things we'll want to use an IoC, register the Dao type with it and later on obtain the Dao instance from the Container

var container = new UnityContainer();
            container.AddNewExtension<Interception>();
            container.RegisterType<IUserDao, DBUserDao>(
                new Interceptor<InterfaceInterceptor>(),
                new InterceptionBehavior<SaveResultBehavior>()
            );

            IUserDao userDao = container.Resolve<IUserDao>();
            var users = userDao.GetUsers("Asturies");

The second part, using a MockDao that will just deserialze the previously saved Entities turned quite more interesting, and is the one that last year gave me some problems and made me resort to Castle Dynamic Proxies. The thing is that we don't want (because should be unnecessary) to define MockDao classes. All the behavior we need (find an entity on disk, deserialize and return to us) can be done by the interception code (the IInterceptionBehavior), so no need to define empty MockDao classes. So we want Unity to create a Proxy implementing the necessary I___Dao interface and has the deserialization behavior. The problem stems from the fact that Intercept.ThroughProxy requires us to give it an instance of the class being intercepted, so we would need a MockDao class... Obviously, Inheritance based proxies have the same problem, as the proxy will inheritn from that MockDao class. This problem quite astonished me, as I had previously achieved the intended behavior with Castle Proxies, using CreateInterfaceProxyWithoutTarget

Proxy without target. This one is tricky. You don’t supply target implementation for the interface. Dynamic Proxy generates it for you at runtime, using interceptors to provide behavior for its methods.

At the time we were quite in a rush with that project, so I did not further investigate if there were some quite of equivalent in Unity and just fell down to Castle, but it left me with some bad taste that I've finally cleaned now.

Googling a bit, there are other 2 guys asking just that, the Unity equivalent to Castle's CreateInterfaceProxyWithoutTarget [1] and [2]. Well, there's a (failing) answer to the second question that put me on the right track for this, we have to use NewInstaceWithAdditionalInterfaces and a Casting, just like this:

IUserDao userDao = (IUserDao)(Intercept.NewInstanceWithAdditionalInterfaces<Object>(
                new VirtualMethodInterceptor(),
                new List<IInterceptionBehavior>(){new RetrieveSavedResultBehavior()},
                new List<Type>() { typeof(IUserDao) }
                ));
            var users = userDao.GetUsers("Asturies");

Using the IoC, there's something more we need to take into account. We can't register a Type, cause the interesting thing of all this is that we're not defining those Mock classes, we're letting the Proxy Generator to do that. Hopefully, we can register a Factory (InjectionFactory) that will take care of calling the Proxy Generator (Unity's Intercept class) to create the proxy, something like this:

container.AddNewExtension<Interception>();
            container.RegisterType<IUserDao>(new InjectionFactory(c =>
            {
                return Intercept.NewInstanceWithAdditionalInterfaces%lt;Object>(
                    new VirtualMethodInterceptor(),
                    new List<IInterceptionBehavior>() { new RetrieveSavedResultBehavior() },
                    new List<Type>() { typeof(IUserDao) }
                );
            }));

            IUserDao userDao = container.Resolve<IUserDao>();

You can download the whole sample from here

In these samples I've been using the simplest form of interception, we just intercept all the methods for one given object (in that case it's just what I needed, serializing/deserializing all the calls on that Dao). However, in many occasions we'll need to discriminate, some of the methods will need that added behavior and others not. One solution here is continue to intercept all calls, and let the code in the Behavior class decide if that method needs the extra functionality or if it just should let the call go through without any further action). Well, that's one options, but in those cases what we really should use is Policy Injection with its mapping rules and call handlers (as explained by Dino Espósito in the third article in the series).

As we saw last month, all intercepted methods on the target object will execute according to the logic expressed in the Invoke method of the behavior object. The basic interception API doesn’t provide you with the ability to distinguish between methods and doesn’t support specific matching rules. To get this, you may resort to the policy injection API.

To wrap-up, I'd like to point out that Microsoft seems to refer to AOP as "Policy Injection" which I think adds some confusion. Seems like I'm not the only one with this impression

When asked why the name Policy Injection and not AOP, Ed answers:
... the reality is most of our customers have not heard of AOP or AOSD. Please put yourself in their shoes for a second. We wanted a name that was reflective of the use and benefit the block brings, rather than using an unfamiliar term that only the exceptions understand. We also wanted to have no implicit expectations on the design that may be inherited from AO solutions.
So Policy Injection is AOP, or at least a part of it. The reason why Microsoft did not choose the term AOP seems to be that AOP could have been perceived as a boring academic concept, which was fashionable in the .NET community about year 2003.

No comments:

Post a Comment