Saturday 5 February 2011

Implementing DI in an AOP Aspect

I'm a big fan of Dependency Injection (DI) and have used it extensively on both Windows and Web applications, with both the Composite Application Block/Smart Client Software Factory and Composite Web Application Block/Web Client Software Factory. It's a great way to "program to an interface, not an implementation" without having to hand-roll your own factory.
I've recently become aware of the capabilities of AOP in general and Gael Fraiteur's PostSharp in particular.  On some recent blog postings I've compared Microsoft's DI framework Unity (version 2.0) with PostSharp to find a way to "automagically" implement NotifyPropertyChanged on C# automatic properties.  In that particular battle, the clear winner is PostSharp. 

Despite being an advocate of DI, the thing I don't like about it is that it starts to permeate your code. WCSF and SCSF are built on top of ObjectBuilder which insists on all abstractions being decorated with [CreateNew] or [ServiceDependency]/[Dependency].  Look at a WCSF/SCSF project and you'll see these attributes all over your Presenter's and other DI consuming class's properties and constructors.  ObjectBuilder was never really built to be used outside of these software factories, whereas Unity is a fully fledged IOC framework that can be used on its own.  As a result Unity has a friendlier API.  For example, if we consider Constructor Injection, one thing that is much better in Unity than ObjectBuilder is that abstractions don't need attributes for Unity to inject its concrete implementations into. 
Consider the code below:

class Program
{
    public static UnityContainer Container;

    static void Main(string[] args)
    {
        Container = new UnityContainer();
        Container.RegisterType<IAmSpartacusSpartacus>();

        GreatFilm gf = Container.Resolve<GreatFilm>();
        gf.Spartacus.ClaimToBeSpartacus();

        Console.ReadLine();
    }
}

public class GreatFilm
{
    public IAmSpartacus Spartacus { getprivate set; }

    public GreatFilm(IAmSpartacus s)
    {
        Spartacus = s;
    }
}

public interface IAmSpartacus
{
    void ClaimToBeSpartacus();
}

public class Spartacus : IAmSpartacus
{
    public void ClaimToBeSpartacus()
    {
        Console.WriteLine("I Am Spartacus!");
    }
}

Firstly, we set up the UnityContainer in Main() and add a type mapping that associates the IAmSpartacus interface with the Spartacus class.  When the GreatFilm constructor gets called the Spartacus class gets injected in for the IAmSpartacus placeholder and all this happens without the need to decorate the constructor with anything to indicate that DI is going to provide the implementation. This is better than ObjectBuilder where we'd need either [CreateNew] (for a new object) or [ServiceDependency] (for a service instance) inside the constructor. 
Things are not much different for Property Injection though, we still have to decorate the property with the [Dependency] attribute for DI to work:

[Dependency]
public IAmSpartacus Spartacus
{
   get;
   private set;
}


The use of the [Dependency] attribute is actually the less pernicious influence of Unity on our code:  More significantly, the set property must now be made public.  We might not want the setter to be public, it might not make sense to make it public, but we have had to change our API in order to hook into DI.   

Similarly, if we look again at the constructor injection code we notice that Unity has also left its footprint on even this very small code fragment.  Firstly we have had to provide GreatFilm with a constructor with an argument (which might not be what we really want) and secondly and more significantly, we have to use Resolve() to create the GreatFilm instance. We can no longer use new because we need Unity to create the object for us for it to do its DI magic.  One might think that we could use a public static Create method and make the constructor private to force clients to use the Create method as follows:

public static GreatFilm Create()
{
   return Program.Container.Resolve<GreatFilm>();
}

private GreatFilm(IAmSpartacus s)
{
}

Except we can't do that because the constructor needs to be public for Unity to be able to call it! Ok, you could next try putting the call to Resolve inside the constructor (as I did) and marvel at the stack overflow you've just crafted!

So Unity is great, but not without some tangible drawbacks:

1. Objects have to be created by the IOC container.  To avoid proliferation of the IOC container across code a strategy for centralising construction needs to be devised.  Clients must then (know that they have to) use this centralised construction.
2. Properties or Constructors have to be made public.
3. Attributes start to appear all over the code (less so for Unity than OB)

So, with my new found liking for PostSharp I wondered whether I could create a PostSharp aspect to "hide" Unity in an attribute class and keep my code just as I want it:

class Program
{
    public static UnityContainer Container;

    static void Main(string[] args)
    {
        Container = new UnityContainer();
        Container.RegisterType<IAmSpartacusSpartacus>();

        GreatFilm gf = new GreatFilm();
        gf.Spartacus.ClaimToBeSpartacus();

        Console.ReadLine();
    }
}

[DependencyInject]
public class GreatFilm
{
     public IAmSpartacus Spartacus { getprivate set; }
 }

public interface IAmSpartacus
{
    void ClaimToBeSpartacus();
}

public class Spartacus : IAmSpartacus
{
    public void ClaimToBeSpartacus()
    {
        Console.WriteLine("I Am Spartacus!");
    }
}

[Serializable]
[MulticastAttributeUsage(
MulticastTargets.InstanceConstructor,
AllowMultiple = false)]
public sealed class DependencyInjectAttribute :
OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        foreach (PropertyInfo p in
        args.Method.DeclaringType.GetProperties())
        {
            if (Program.Container.IsRegistered(p.PropertyType))
            {
                p.SetValue(args.Instance,
                Program.Container.Resolve(p.PropertyType), null);
            }
        }
    }
}

Looking at Main, we still set up the UnityContainer with the IAmSpartacus to Spartacus mapping.  But now we can simply new up the object (no call to Resolve) and call the default constructor.  Because the class is decorated with our custom [DependencyInject] attribute PostSharp intervenes to call the OnEntry method of the DependencyInjectAttribute class. The class is decorated with an attribute [MultiCastTargets.InstanceConstructor] which tells the code to execute when a ctor is being invoked.  The code then iterates through the attributed target's properties and sets any Unity registered interfaces to the implementation class that the interface is registered against. All we have to do now is put our custom [DependencyInject] attribute on any class we want DI to kick in. PostSharp even allows us to put this directive in AssemblyInfo.cs, negating the need for any class-based attributes.
Looking at the code fragment, we still have a private Property setter and we can just go with the default constructor, there is no need to have to add a parameter to the constructor.  Clients can just go ahead and new the object - they don't have to call Resolve() or some static Create() method that we wrote to do the same.  In summary then, this solution is less intrusive on the original code.
And there we have it! Obviously this code is just a Proof Of Concept, but I hope it's presented some food for thought. AOP and DI are different frameworks with different purposes. DI is perfect for being able to provide a factory which squirts in an implementation class for an abstraction; and AOP is perfect for cross-cutting concerns.  In this very simple POC, the two frameworks work together: DI (Unity) provides the factory and AOP (PostSharp) encapsulates it as a cross-cutting concern, without treading on our code and forcing changes to it.

No comments:

Post a Comment