Unity Automapper 1.2 released


Unity Automapper is probably nearly finished. There aren’t many features left that I want to implement without over-complicating things – which is one of the main goals I want to avoid. Things I am looking at include adding a mechanism to allow an assembly to provide configuration details rather than attributes placed directly on types, and possibly the ability to provide an explicit list of interfaces to map rather than a seek-out-all-interfaces approach. Version 1.2 contains a single feature which should make using AOP in Unity much, much easier in Unity: the [PolicyInjection] attribute. By marking this attribute on any interfaces, mappings automatically participate in Policy Injection using interface-based-interception. Confused? Read on.

The Problem with Interception

I’ve blogged about Unity Interceptors several times before, and how they can provide cleaner code for you etc. The biggest difficulties to adopting them that I’ve seen are: –

  • Difficulty in understanding the interception pipeline and how AOP works.
  • Difficulty in setting up interceptors or call handlers.

The first one can be overcome with an explanation of what AOP is, and some simple diagrams. The second is more problematic. Let’s assume we have a simple Call Handler that logs method entry and exit calls into the console that we want to apply via an attribute onto methods: –

public class LoggingCallHandler : ICallHandler
{
	public int Order { get; set; }
	public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
	{
		var methodName = input.MethodBase.Name;
		Console.WriteLine("Entering method {0}", methodName);
		var result = getNext()(input, getNext);
		Console.WriteLine("Exiting method {0}", methodName);
		return result;
	}
}

To get this to work in Unity you have to do several steps: –

  1. Create an Attribute and apply it onto the method that you want the call handler to apply onto. (Note: You can use the TagAttribute instead of your own attribute, which is weakly-typed but doesn’t require you to create a custom attribute).
  2. Turn on Interception in Unity by adding the Interception Extension.
  3. Set up a policy which applies that call handler under a given matching rule, in our case the CustomAttributeMatchingRule.
  4. Register the actual interface mapping in Unity with two overrides: –
    • Apply the PolicyInjection interception behaviour to tell Unity that this type takes part in Policy Injection
    • Apply the Interface Interceptor to tell Unity to construct interface-based proxies rather than interitance-based proxies

public class LoggingAttribute : Attribute { }
public interface IThing { [Logging] void Foo(); }

var container = new UnityContainer();

//Turn on interception
container.AddNewExtension();

// Create a policy for this logging handler.
container
   .Configure()
   .AddPolicy("Logging")
   .AddMatchingRule(new CustomerAttributeMatchingRule(typeof(LoggingAttribute), false))
   .AddCallHandler();

//Set up IThing to participate in Policy Injection
container.RegisterType<IThing, Thing>(new InterceptionBehavior(),
                                      new Interceptor());

Worse still, you would have to repeat the three policy lines for every call handler you used, and would have to explicitly provide those two overrides of every type registration in Unity. For someone who has never used interception, it’s a lot to take in.

Interceptor is by definition a more advanced topic but it allows many, many benefits, encouraging composition and reusability – so it should be as easy as possible to use. Many people I know aren’t even aware of the AOP side of Unity (or other IoC containers), or if they are, they’re scared off by it due to the difficulty of configuration.

Making Interception Easier

There are several stages that make interception easier with Unity. Let’s assume that your Call Handler is already created, as above. You want to apply that handler to a class using an attribute. It turns out that the easiest way to do that is to use the HandlerAttribute that comes built into Unity. So here our LoggingAttribute inherits from HandlerAttribute instead of the base Attribute: –

public class LoggingAttribute : HandlerAttribute
{
	public override ICallHandler CreateHandler(IUnityContainer container)
	{
		return new LoggingCallHandler();
	}
}

This special Attribute automatically does away with the need to explicitly set up a policy using the AttributeMatchingRule etc. – you simply apply it as required and Unity will automatically create a policy for you. To make life simpler, you can even have your call handler inherit from HandlerAttribute and return itself on the overridden call to CreateHandler, reducing the number of classes floating around.

The second part I mentioned earlier is the mapping of your client types in Unity that use the Call Handler: You normally need to register them for Policy Injection, but with the Automapper, you can now simply decorate your interface with the [PolicyInjection] attribute – this then automatically registers the type to be set up for policy injection. So the original source code sample which performs the Unity registration and policy creation above now looks like this: –

[PolicyInjection] 
public interface IThing 
{ 
    [Logging] 
    void Foo(); 
} 

var container = new UnityContainer(); 
container.AutomapAssemblies(Assembly.GetExecutingAssembly().FullName);

So no need to: –

  1. Turn on the Interception extension – automatically done by Automapper if needed.
  2. Manually set up policies in Unity – automatically done as LoggingAttribute inherits from HandlerAttribute.
  3. Manually register IThing for policy injection – automatically done by Automapper because of the [PolicyInjection] attribute.

Much nicer Smile

Conclusion

The Unity Automapper, in conjunction with the in-built HandlerAttribute, makes it possible to create and apply call handler in a completely configuration-free manner: –

  1. Create your call handler as normal.
  2. Ensure that it inherits from HandlerAttribute.
  3. Apply your Attribute as required.
  4. Ensure that the interfaces that it is used on have the [PolicyInjection] attribute applied.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s