Unity, interception, and AOP..

While I’ve understood Dynamic Proxies, Interception, and AOP conceptually and used them in personal projects, my first production-level encounter was last year. We utilized Unity’s interception features for seemingly minor tasks. Despite achieving the desired outcome, some aspects remained unclear, partly due to time constraints that rushed my reading of Unity’s documentation.

Dino Esposito’s insightful series [[1, 2 and 3] prompted me to revisit and clarify this experience.

It’s crucial to differentiate between AOP and Dependency Injection. However, most modern IoC containers, including Spring.Net, Castle Windsor, and Unity, offer rudimentary AOP support, primarily for intercepting method calls to add aspects like logging, validation, or security.

This runtime method interception is achieved through Proxy Objects, which either reference the intercepted instance (composition) or inherit from the intercepted class. Although this concept is shared among Spring, Castle, and Unity, some aspects of Unity can be confusing:

  • Unity 2.0 operates independently from Enterprise Library, connected only by their shared developer: Patterns and Practices. Using Unity’s lightweight AOP only requires adding these assemblies:
    • Microsoft.Practices.ServiceLocation
    • Microsoft.Practices.Unity
    • Microsoft.Practices.UnityInterception
  • Unity prefers “Interceptor” over “Proxy.” While it lacks a “ProxyGenerator” class like Castle, the “Intercept” class fulfills the proxy creation role.
  • Unity implements interception through a chain of IInterceptionBehavior objects, each encapsulating injected logic. This is analogous to Castle’s IInterceptor.

Unity provides two Composition-based proxy types (Instance Interceptor) for wrapping existing object instances: InterfaceInterceptor and TransparentProxyInterceptor. Additionally, it offers one Inheritance-based proxy type (Type Interceptor): VirtualMethodInterceptor.

Creating and using proxies without an IoC container is possible, but for decoupled and extensible production applications, container-based creation is recommended.

Let’s illustrate with examples inspired by last year’s project. Imagine needing to mock a Data Source. The goal is to serialize Data Entities from real DAOs and subsequently use those serialized versions instead of querying the real DAOs or Data Source.

Injecting a serialization behavior into the real DAOs can be achieved by wrapping them in a Proxy. This Proxy would first delegate to the real DAO to retrieve entities (e.g., from a database) and then serialize them before returning to the unaware caller.

We can manually create this Proxy (using an InterfaceInterceptor, a Composition-based approach):

1
2
3
4
5
IUserDao userDao = new DBUserDao();
            IUserDao userDaoProxy = Intercept.ThroughProxy(userDao,
                new InterfaceInterceptor(), new\[\] { new SaveResultBehavior() }
            );
            var users = userDaoProxy.GetUsers("Asturies"); 

For decoupling, we’d employ an IoC container, register the DAO type, and resolve it to get the proxied instance:

1
2
3
4
5
6
7
8
9
var container = new UnityContainer();
            container.AddNewExtension();
            container.RegisterType(
                new Interceptor(),
                new InterceptionBehavior()
            );

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

A more intriguing challenge arose when we needed a MockDao to deserialize previously saved entities. Creating dedicated MockDao classes seemed redundant since the desired behavior (finding, deserializing, and returning entities from disk) could be entirely handled by the interception logic (IInterceptionBehavior). We wanted Unity to dynamically generate a Proxy implementing the required I___Dao interface and incorporating the deserialization behavior. However, Intercept.ThroughProxy necessitates an instance of the intercepted class, implying the need for a MockDao class. Inheritance-based proxies posed the same issue, inheriting from the nonexistent MockDao.

This limitation was surprising, 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.

Under project constraints, I didn’t delve into a Unity equivalent and resorted to Castle. However, this unresolved question lingered until recently.

Upon researching, I found two similar queries about the Unity equivalent of Castle’s CreateInterfaceProxyWithoutTarget: [1] and [2]. A (flawed) response to the second question pointed me in the right direction: utilize NewInstaceWithAdditionalInterfaces and casting:

1
2
3
4
5
6
7
8
IUserDao userDao = (IUserDao)(Intercept.NewInstanceWithAdditionalInterfaces(
                new VirtualMethodInterceptor(),
                new List(){new RetrieveSavedResultBehavior()},
                new List() { typeof(IUserDao) }
                ));
            var users = userDao.GetUsers("Asturies");

To leverage the IoC container, we encounter another consideration. Registering a specific type is not feasible since we're aiming to avoid defining Mock classes, letting the Proxy Generator handle that. Instead, we can register a Factory (InjectionFactory) responsible for invoking the Proxy Generator (Unity's Intercept class) to create the proxy:

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

        IUserDao userDao = container.Resolve(); 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

The complete code sample is available for download at [from here](http://www.telecable.es/personales/covam1/deployToNenyures/SourceCode/Interception.Net.zip).

These examples demonstrate basic interception, targeting all methods of a specific object. However, in many scenarios, selective interception is necessary. While one option is to intercept all calls and let the Behavior class decide whether to apply additional functionality or pass through, a more elegant approach is using Policy Injection with its mapping rules and call handlers, as described by Dino Esposito in [third article](http://msdn.microsoft.com/en-us/magazine/gg598927.aspx).

_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 doesnt provide you with the ability to distinguish between methods and doesnt support specific matching rules. To get this, you may resort to the policy injection API._

Finally, I'd like to address the potential confusion arising from Microsoft's use of "Policy Injection" to refer to AOP. It seems that [I'm not the only one with this impression](http://www.sharpcrafters.com/aop.net/policy-injection)

_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._ 
Licensed under CC BY-NC-SA 4.0
Last updated on Jan 27, 2023 13:37 +0100