February 2011

Volume 26 Number 02

Cutting Edge - Policy Injection in Unity

By Dino Esposito | February 2011

In the past two libraries support it. Unity is no exception. The main purpose of AOP is to let developers more effectively deal with crosscutting concerns. In essence, AOP addresses the following question: When you design an object model for an application, how do you deal with aspects of the code such as security, caching or logging? These aspects are key to implementation, but don’t strictly belong to the objects in the model you’re building. Should you spoil your design to incorporate non-business aspects? Or are you better off decorating your business-oriented classes with additional aspects? If you choose the latter, AOP basically provides a syntax to define and attach these aspects.

An aspect is the implementation of a crosscutting concern. In the definition of an aspect, you need to specify a few things. First, you need to provide the code for the concern you implement. In AOP jargon, this is known as the advice. An advice is applied to a specific point of code—whether the body of a method, the getter/setter of a property or perhaps an exception handler. This is known as the join point. Finally, in AOP jargon, you find pointcuts. A pointcut represents a collection of join points. Usually, pointcuts are defined by criteria using method names and wildcards. AOP ultimately acts in the runtime to inject the code of the advice before, after and around the join point. An advice then is associated with a pointcut.

In the previous articles, I explored the interception API of Unity. The API lets you define advices to attach to classes. In Unity jargon, the advice is a behavior object. You typically attach the behavior to a type that’s resolved via the IoC mechanism of Unity, even though the interception mechanism doesn’t strictly require the IoC functionality. In fact, you can configure interception to apply also to instances created via plain code.

A behavior consists in a class that implements a fixed interface—the IInterceptionBehavior interface. The interface features a method named Invoke. By overriding this method, you actually define the steps you want to be executed before or after the regular method call, or both. You can attach a behavior to a type using fluent code as well as a configuration script. In this way, all you do is define a join point. But what about pointcuts?

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.

Policy Injection and PIAB

If you’ve used versions of the Microsoft Enterprise Library (EntLib) prior to the latest version, 5.0, you may have heard about Policy Injection Application Block (PIAB), and chances are that you also took advantage of it in some of your applications. EntLib 5.0 also features a PIAB module. So what’s the difference between the Unity policy injection and EntLib PIAB?

In EntLib 5.0, PIAB exists mostly for compatibility reasons. The content of the PIAB assembly changed in the new version. In particular, all the machinery for interception is now part of Unity and all system-provided call handlers in earlier versions of EntLib were moved to other assemblies, as shown in Figure 1.

Figure 1 Refactoring of Call Handlers in the Microsoft Enterprise Library 5.0

Call Handler New Assembly in Enterprise Library 5.0
Authorization handler Microsoft.Practices.EnterpriseLibrary.Security.dll
Caching-handling handler Removed from PIAB
Exception-handling handler Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll
Logging handler Microsoft.Practices.EnterpriseLibrary.Logging.dll
Performance-counter handler Microsoft.Practices.EnterpriseLibrary.PolicyInjection.dll
Validation handler Microsoft.Practices.EnterpriseLibrary.Validation.dll

As you can see in Figure 1, each call handler was moved to the assembly of the associated application block. So the exception-handling call handler moved to the exception-handling application block and the validation handler moved to the validation-application block and so on. The only exception to this rule was the performance-counter handler, which moved to the PolicyInjection assembly. Although the assemblies changed, the namespace of the classes remained just the same. It’s also worth noting that, due to security concerns, the caching call handler previously included in PIAB was removed from EntLib 5.0 and made available only through the EntLib Contrib CodePlex Web site at bit.ly/gIcP6H. The net effect of these changes is that PIAB is now made of legacy components available just for backward compatibility that still require some code changes to compile with version 5.0. Unless you have serious legacy dependencies, the recommended approach is that you upgrade your policy injection layers to take advantage of the new (and largely similar) policy injection API baked into the Unity application block. Let’s find out more about policy injection in Unity.

Policy Injection at a Glance

Policy injection is a layer of code that extends the basic Unity interception API to add mapping rules and call handlers on a per-method basis. Implemented as a special interception behavior, policy injection consists of two main phases: initialization and execution time.

During the initialization phase, the framework first determines which of the available policies can be applied to the target method being intercepted. In this context, a policy is described as a set of operations that can be injected in a particular order between the object being intercepted and its actual caller. You can only intercept methods on objects (either existing instances or newly created instances) that have been explicitly configured for policy injection.

Having figured out the list of applicable policies, the policy injection framework prepares the pipeline of operations (an operation is referred to as a call handler). The pipeline results from the combination of all the handlers defined for each of the matching policies. The handlers in the pipeline are sorted based on the order of the policy and the priority assigned to each handler in the parent policy. When a policy-enabled method is invoked, the previously built pipeline is processed. If the method, in turn, places calls to other policy-enabled methods on the same object, the handler pipelines of those methods are merged into the main pipeline. 

Call Handlers

A call handler is more specific than a “behavior” and really looks like an advice, as it was originally defined in AOP. Whereas a behavior applies to a type and leaves to you the burden of taking different actions for different methods, a call handler is specified on a per-method basis.

Call handlers are composed in a pipeline and invoked in a predetermined order. Every handler is able to access details of the call, including method name, parameters, return values and expected return type. A call handler can also modify parameters and return values, stop the propagation of the call down the pipeline and raise an exception.

It’s interesting to note that Unity doesn’t come with any call handlers. You can only create your own, or reference application blocks from EntLib 5.0 and use any of the call handlers listed in Figure 1.

A call handler is a class that implements the ICallHandler interface, like this:

public interface ICallHandler
{
  IMethodReturn Invoke(

    IMethodInvocation input, 

    GetNextHandlerDelegate getNext);
  int Order { get; set; }
}

The Order property indicates the priority of this handler related to all others. The Invoke method returns an instance of a class that contains any return value from the method.

The implementation of a call handler is quite simple in the sense that it’s just expected to do its own specific things and then let the pipeline go. To yield control to the next handler in the pipeline, the handler calls the getNext parameter it receives from the Unity runtime. The getNext parameter is a delegate defined as:

public delegate InvokeHandlerDelegate GetNextHandlerDelegate();

In turn, the InvokeHandlerDelegate is defined as:

public delegate IMethodReturn InvokeHandlerDelegate(

  IMethodInvocation input,

  GetNextHandlerDelegate getNext);

The Unity documentation provides a clear diagram that illustrates interception. In Figure 2, you see a slightly modified diagram that presents the architecture of policy injection.

image: The Call Handler Pipeline in the Unity Policy Injection

Figure 2 The Call Handler Pipeline in the Unity Policy Injection

Within the boundaries of a system-provided policy injection behavior, you see the chain of handlers to process a given method invoked on a proxy object or derived class. To complete the overview of policy injection in Unity, we need to take a look at matching rules.

Matching Rules

Through a matching rule, you specify where to apply your interception logic. If you use behaviors, your code applies to the entire object; with one or more matching rules, you can define a filter. A matching rule indicates a criterion to select objects and members to which Unity will attach a handler pipeline. Using AOP terminology, a matching rule is the criterion that you use to define the pointcuts. Figure 3 lists the matching rules natively supported by Unity.

Figure 3 List of Supported Matching Rules in Unity 2.0

Matching Rule Description
AssemblyMatchingRule Selects target objects based on types in the specified assembly.
CustomAttributeMatchingRule Selects target objects based on a custom attribute at the member level.
MemberNameMatchingRule Selects target objects based on member name.
MethodSignatureMatchingRule Selects target objects based on 
the signature.
NamespaceMatchingRule Selects target objects based on 
the namespace.
ParameterTypeMatchingRule Selects target objects based on the type name of a parameter for a member.
PropertyMatchingRule Selects target objects based on member 
names, including wildcard characters.
ReturnTypeMatchingRule Selects target objects based on the return type.
TagMatchingRule Selects target objects based on the value assigned to an ad hoc 
Tag attribute.
TypeMatchingRule Selects target objects based on the type name.

A matching rule is a class that implements the IMatchingRule interface. Armed with this knowledge, let’s see how to work with policy injection. There are essentially three ways in which you can define policies: using attributes, using fluent code and via configuration.

Adding Policies via Attributes

Figure 4 shows an example call handler that throws an exception if the result of an operation is negative. I’ll be using this same handler in various scenarios.

Figure 4 The NonNegativeCallHandler Class

public class NonNegativeCallHandler : ICallHandler
{
  public IMethodReturn Invoke(IMethodInvocation input,
                              GetNextHandlerDelegate getNext)
  {
    // Perform the operation
    var methodReturn = getNext().Invoke(input, getNext);
    // Method failed, go ahead
    if (methodReturn.Exception != null)
    return methodReturn;
    // If the result is negative, then throw an exception
    var result = (Int32) methodReturn.ReturnValue;
    if (result <0)
    {
      var exception = new ArgumentException("...");
      var response = input.CreateExceptionMethodReturn(exception);
      // Return exception instead of original return value
      return response;
    }
    return methodReturn;
  }
  public int Order { get; set; }
}

The simplest way to use the handler is by attaching it to any method where you think it can be useful. For this, you need an attribute, such as:

public class NonNegativeCallHandlerAttribute : HandlerAttribute
{
  public override ICallHandler CreateHandler(

    IUnityContainer container)
  {
    return new NonNegativeCallHandler();
  }
}

Here’s a sample Calculator class that you decorate with attribute-based policies:

public class Calculator : ICalculator 
{
  public Int32 Sum(Int32 x, Int32 y)
  {
    return x + y;
  }
  [NonNegativeCallHandler]
  public Int32 Sub(Int32 x, Int32 y)
  {
    return x - y;
  }
}

The result is that calls to method Sum proceed as usual regardless of the returned value, whereas calls to method Sub will throw an exception if a negative number is returned.

Using Fluent Code

If you don’t like attributes, you can express the same logic via a fluent API. In this case, you must provide many more details as far as matching rules are concerned. Let’s see how to express the idea that we want to inject code only in methods that return an Int32 and are named Sub. You use the fluent API to configure the Unity container (see Figure 5).

Figure 5 Fluent Code to Define a Set of Matching Rules

public static UnityContainer Initialize()
{
  // Creating the container
  var container = new UnityContainer();
  container.AddNewExtension<Interception>();
  // Adding type mappings
  container.RegisterType<ICalculator, Calculator>(
    new InterceptionBehavior<PolicyInjectionBehavior>(),
    new Interceptor<TransparentProxyInterceptor>());
  // Policy injection
  container.Configure<Interception>()
    .AddPolicy("non-negative")
    .AddMatchingRule<TypeMatchingRule>(
      new InjectionConstructor(
        new InjectionParameter(typeof(ICalculator))))
    .AddMatchingRule<MemberNameMatchingRule>(
      new InjectionConstructor(
        new InjectionParameter(new[] {"Sub", "Test"})))
    .AddMatchingRule<ReturnTypeMatchingRule>(
      new InjectionConstructor(
        new InjectionParameter(typeof(Int32))))
    .AddCallHandler<NonNegativeCallHandler>(
      new ContainerControlledLifetimeManager(),
        new InjectionConstructor());
  return container;
}

Note that if you use the ContainerControlledLifetimeManager manager, you’re guaranteed that the same call handler instance is shared by all of the methods.

The effect of the code is that any concrete type that implements ICalculator (that is, is configured to be intercepted and is resolved through Unity) will select two potential candidates for injection: methods Sub and Test. However, only methods with an Int32 return type will survive the further matching rule. This means that, for example, Test will be ruled out if it happens to return a Double value.

Adding Policies Through Configuration

Finally, the same concept can be expressed using the configuration file. Figure 6 shows the expected content of the <unity> section.

Figure 6 Preparing Policy Injection in the Configuration File

public class NonNegativeCallHandler : ICallHandler
{
  public IMethodReturn Invoke(IMethodInvocation input, 
                              GetNextHandlerDelegate getNext)
   {
     // Perform the operation  
     var methodReturn = getNext().Invoke(input, getNext);
     // Method failed, go ahead
     if (methodReturn.Exception != null)
       return methodReturn;
     // If the result is negative, then throw an exception
     var result = (Int32) methodReturn.ReturnValue;
     if (result <0)
     {
       var exception = new ArgumentException("...");
       var response = input.CreateExceptionMethodReturn(exception);
       // Return exception instead of original return value
       return response;   
     }
     return methodReturn;
   }
    public int Order { get; set; }
}
<unity xmlns="https://schemas.microsoft.com/practices/2010/unity">
  <assembly name="PolicyInjectionConfig"/>
  <namespace name="PolicyInjectionConfig.Calc"/>
  <namespace name="PolicyInjectionConfig.Handlers"/>
  <sectionExtension  ... />
  <container>
    <extension type="Interception" />
    <register type="ICalculator" mapTo="Calculator">
      <interceptor type="TransparentProxyInterceptor" />
      <interceptionBehavior type="PolicyInjectionBehavior" />
    </register>
    <interception>
      <policy name="non-negative">
        <matchingRule name="rule1" 
          type="TypeMatchingRule">
          <constructor>
             <param name="typeName" value="ICalculator" />
          </constructor>
        </matchingRule>
        <matchingRule name="rule2" 
          type="MemberNameMatchingRule">
          <constructor>
            <param name="namesToMatch">
              <array type="string[]">
                <value value="Sub" />
              </array>
            </param>
          </constructor>
        </matchingRule>
        <callHandler name="handler1" 
          type="NonNegativeCallHandler">
          <lifetime type="singleton" />
        </callHandler>                    
      </policy>
    </interception>
            
  </container>
</unity>

As it turns out, when you have multiple matching rules in a single policy, the final result is the Boolean operator AND applies to all of them (meaning all of them must be true). If you’ve defined multiple policies, then each one is evaluated for matching—and handlers applied—independently. Therefore, you can get handlers applied from different policies.

Interception at a Glance

To recap, interception is the way in which most IoC frameworks in the Microsoft .NET Framework space implement aspect orientation. Through interception, you’re given the chance of running your own code before or after any given method in any given type in any given assembly. EntLib in the past provided a specific application block, PIAB, for achieving this. In EntLib 5.0, the underlying engine of PIAB has been moved into Unity and implemented as a special behavior for the Unity low-level interception API that I covered in my previous two columns. The policy injection behavior requires the use of a Unity container and won’t work only through the low-level interception API.

The low-level interception API, however, doesn’t let you select the type members you want to intercept; you have to write the code to do that yourself. With the policy injection behavior, though, you can concentrate on the details of the behavior you want, and let the library take care of figuring out which methods it applies to based on the rules you give it.


Dino Esposito is the author of “Programming Microsoft ASP.NET MVC” (Microsoft Press, 2010) and coauthored “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2008). Based in Italy, Esposito is a frequent speaker at industry events worldwide.

Thanks to the following technical expert for reviewing this article: Chris Tavares