Wednesday, July 22, 2009

Unity with config free AOP

At the current place of work i have managed to introduce the notion of IoC and DI. As the team was using EntLib i investigated Unity and found it to be a suitable replacement for Windsor or SM considering how we were going to be using it.
We have just started up a new project and i have asked one of the lads to investigate AOP with unity, what we found was a pretty simple solution for our initial requirement, logging the service calls using Unity

Below is the 3 files that make up the spike. it very trivial, but there is some pretty average info on how Unity work, there is sample (like this) but with little explanation as to what is going on. David Hayden is probably the first port of call for more info (note you will need to reference Unity 1.2 and Unity Interception).
Note we are using the TransparentProxyInterceptor not the InterfaceInterceptor, which i believe is broken as it does not handle inheritance, which in an OO world is not good enough.

class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<ITalker, Talker>();
container.AddNewExtension
<Interception>();
container.Configure
<Interception>().
SetDefaultInterceptorFor
<ITalker>(new TransparentProxyInterceptor()).
AddPolicy("Logging").
AddMatchingRule(new TypeMatchingRule(typeof(ITalker))).
AddCallHandler(typeof(LoggerHandler));



Console.WriteLine("This is the start");
container.Resolve
<ITalker>().Talk();
Console.WriteLine("This is the end");
Console.ReadLine();
}
}

public interface ITalker
{
void Talk();
}

public class Talker : ITalker
{
public void Talk()
{
Console.WriteLine("helllllllooooo!");
}
}

public class LoggerHandler : ICallHandler
{
public LoggerHandler()
{
Order = 0;
}

public int Order { get; set; }

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate
etNext)

{
Console.WriteLine("** I'm in!**");
var result = getNext().Invoke(input, getNext);
Console.WriteLine("** Out I go :) **");
return result;
}
}

---------------------------------------------------------
Which returns :
This is the start
** I'm in!**
helllllllooooo!
** Out I go :) **
This is the end
---------------------------------------------------------
*Sorry about the formatting, this is done with out WLW*

7 comments:

Lee Campbell said...

How would you compare Unity as an AOP framework compared to PostSharp. IN WPF a very common task is to use the INotifyPropertyChanged interface which exposes the single event that is raised in the setters of properties. This gives wpf its auto-updating feel.

As you can imagine putting the event raiser in every property setter is painful so in Postsharp you can just attribute up a class/property with an attribute and let it do it for you which is great. (see here).

Can Unity do this as elegantly?

RhysC said...

At a guess i would say "yes" it seems to be able to do the interception as well as PostSharp, the problem is with the resolution of types. PostSharp brute forces its way into the code where as Unity intercepts at run time. For this reason you get issues with certain interceptors (e.g. Interface based ones not coping with inheritance etc).
I would give it a go if i was using WPF as i prefer to have all of that guff out of the class (as you have done) and using one Ioc and Aop is a plus in my book. If you are using Untity give me a call and we will test it out. To be honest the code should look almost indetical bar some basic API variants

shecht said...

The answer to Lee's question is: it depends on how you define elegance. I managed to do the type attribute magic with a custom matching rule:

http://shecht.wordpress.com/2009/12/12/inotifypropertychanged-with-unity-interception-aop/

RhysC said...

Just be aware that the type must be constraucted from the container for Unity to do anything, typically i do not "resolve" models (domain, view models etc or DTOs) from a container. They are just created, whether inline, or via a factory. If you are using AOP for a model i would still lean towards something like Postsharp. As a side note i dont use WPF so i cant really say what i do for this situation

Lee Campbell said...

This seems to be the problem for me too. My classes that implement INotifyPropertyChanged have no behaviour so I don't construct them via a container. Looks like PostSharp still wins...? It does make my compile time slow tho!

shecht said...

Actually, Unity has container.BuildUp<T>(obj), while Policy Injection (which is really a config-friendly Unity Interception wrapper) has policyInjection.Wrap<T>(obj), so your factory should work just fine.

I'll have the detailed followup post ready in a couple of days.

shecht said...

@Lee, compilation time is the least problem considering Unity's runtime performance.