Long live “Dependency Resolution”!

OK, so I’m not really serious – but I got your attention right? Truth is, I personally love Dependency Injection, but that doesn’t mean it isn’t without its flaws. The Service Locator pattern is often touted as Dependency Injection’s nearest rival, so let’s very briefly examine some of the characteristics of each of these to see what works and what doesn’t.

What is great about these patterns?

It is hard to condense my enthusiasm into just a few bullet points! I’m also sure I’ve missed some, but just to get our minds in sync;

1.       Testability; the loose coupling of your implementations means you can easily substitute mock classes, enabling your tests to focus on a single “unit”. You can also supply different implementations to allow testing at all (e.g. replace the calls to HttpContext.Current when you have no HttpContext).

2.       Design approach; enforcing loose coupling helps to encourage good design. It helps to shield consumers from the service’s implementation, enabling you to swap implementation if necessary.

3.       Configuration; there is often a big push towards highly configurable containers, both from the point of view of behaviour and their contents. This gives systems a feeling of agility, and the ability to adapt to different deployments or reuse in future systems.

4.       Object lifetime management flexibility; objects can be cached, be a singleton, or be short lived – all controlled through configuration.

What is wrong with Dependency Injection?

There are some potentially painful issues with DI;

1.       I find it counter intuitive that often some object somewhere needs to remember to “Build Up” an object. In other words, the chain of iterating over objects to fulfil their dependencies needs to start somewhere. This can be abstracted into HttpModules, framework code, and so on, but I still don’t like this. An object’s consumer shouldn’t need to know that X must be done before Y will work if at all possible.

2.       When using property injection you generally need to mark your dependencies as public. This can seem counter intuitive, and certainly limits some use cases. Constructor injection can help here though.

3.       Reflection; most (perhaps all?) Dependency Injection containers rely on some extent on Reflection – dynamically inspecting objects and determining their dependencies. I know there are optimisations out there for this, but the fact still remains that this can be an overhead.

4.       Object chains can become quite large. If they’re needed this is no problem, but what if they’re not? Consider this code;

public class Chain

{

    [CreateNew]

    public Customer PrimaryCustomer { get; set; }

    [CreateNew]

    public Partner Partner { get; set; }

    [CreateNew]

    public ProductCatalogue Catalogue { get; set; }

    [CreateNew]

    public AddressLookupService AddressLookup { get; set; }

 

    public string GetPrimaryCustomerName()

    {

        return PrimaryCustomer.Name;

    }

}

 

public class SecurityService

{

    [CreateNew]

    public LoginProvider Login { get; set; }

    [CreateNew]

    public RoleProvider Role { get; set; }

    [CreateNew]

    public TraceProvider Trace { get; set; }

    [CreateNew]

    public AuditService Audit { get; set; }

}

OK, so it isn’t meant to be nice code, so please don’t flame me J. Still, you see the point? If all I want to do is call GetPrimaryCustomerName, and all that uses is one single dependency, my container will still have created instances of all my other types and populated the dependencies of my Chain object... and of course done the same to all the dependent objects. This could quite easily lead to an increase 10-fold in needless object creation and initialisation! “Use a singleton” I hear you say – sure, if applicable. But why use a pattern that has an enormous design impact on my code purely to reduce object creation just because my DI container is doing something slightly crazy? And even if I’m not creating objects, I’m still resolving their references.

What is wrong with Service Locator?

My main bug-bear with Service Locator is that it permeates throughout all my code. And most importantly, every object I write must know about the Service Locator in order to be able to fetch its dependencies.

Consider the following code adapted from the example above;

public class Chain

{

    public string GetPrimaryCustomerName()

    {

        Customer primaryCustomer = ServiceContainer.Resolve<Customer>();

        return primaryCustomer.Name;

    }

}

This is must nicer – but it does mean my Chain class needs to know how to get hold of a Customer. Is this really so different to just creating a new one? Obviously you get the configurability of the Service Locator, but the separation of concerns is wrong in my opinion.

I should point out at this point that some clever people I know actually positively like this approach – they want to be explicit about fetching services and working with them. I see their point, and guess this comes down to personal preference, but the key is, if you like this approach chances are you don’t like DI at all – so this article is hopefully still of interest!

Lazy Dependency Resolution

So can’t we get the benefits of Dependency Injection and Service Locator without some of the drawbacks? I hope so; enter “Lazy Dependency Resolution” (which I already seem to keep abbreviating to just “Dependency Resolution”).

This is actually nothing new; I’ve just given it a name that sounds appropriate, having found a use for a new framework I’ve been playing with. Really, this is an approach cobbled together from various ideas and sources, and some similar ideas flying around “out there” on the web, but then that’s where all the best patterns start I think!

With the advent of static weavers that allow us to intercept calls using Aspect Oriented Programming techniques (see my previous article), we suddenly have an opportunity. The fact of the matter is that the Service Locator pattern does pretty much everything your average DI framework does, except that the service consumer needs some knowledge about how to call the Service Locator. Well, if we pull that concept out of our consumer classes and stuff it into a shiny new Aspect, what do you get? I think you get an implementation of a “Lazy Service Locator” that isn’t tightly coupled into the service consumer.

Enough talk, show me the code!

An Example with PostSharp

I’ve chosen to use PostSharp here as I’ve been playing with it a bit recently, but the idea is based on the concept of static weavers in general. If you want to know why this matters, read my previous article! </shameless-plug>

Quick Disclaimer: Note that this sample is really really rough-and-ready. It is not meant to be neat and tidy – it is just showing an alternative approach that I like. The reality is that I think some of the AOP libraries could help a bit by providing alternative interception models, support for explicitly only targeting properties a little more easily, or better ways of manipulating arguments and return values.

Anyway, for the simple demo we need two classes that must be loosely coupled; a consumer and a provider. The consumer consumes the provider... so to keep this dependency nice and flexible we’ll use an interface for our provider (so we could mock it if we liked, or switch implementations, etc).

public interface IProvider

{

    void PrintId();

}

I told you this was going to be a simple example J

Next we need a consumer class that makes a call to an IProvider implementation;

public class Consumer

{

    public IProvider Provider { get; set; }

 

    public void DisplayInfo()

    {

        Provider.PrintId();

    }

}

As you can see, we simply declare that we need an IProvider using a property here; we don’t specify where we get this from, or what concrete implementation we’re using. This matches how many Dependency Injection frameworks string objects together. Next, let’s have a concrete IProvider implementation (although we could have many different implementations if we liked);

public class ConcreteProvider : IProvider

{

    private Guid _id = Guid.NewGuid();

 

    public void PrintId()

    {

        Console.WriteLine(String.Format("My ID is {0}.", _id));

    }

}

So what I want to be able to do now is call my Consumer class in a completely transparent way, avoiding calls to build the object up, or fetch it from a factory, etc;

public class Program

{

    static void Main(string[] args)

    {

        Consumer consumer = new Consumer();

        consumer.DisplayInfo();

    }

}

OK, build it, run it... oh wait, we got a NullReferenceException because the Provider property is null.

Somehow, then, we want to tell our Consumer class which IProvider implementation it should be using. Well consider the following Aspect code;

[Serializable]

public class DependencyResolutionAspect : OnMethodInvocationAspect

{

    public override void OnInvocation(MethodInvocationEventArgs eventArgs)

    {

        eventArgs.ReturnValue = ServiceContainer.Resolve(

                eventArgs.Delegate.Method.ReturnType);

    }

}

What this is doing is inspecting the declared return type of the method call we’re currently intercepting, and then looking up an implementation in a Service Container to return to the caller. This Service Container could be a facade to any number of registry techniques, so I’ve not included the code. Of course, this means it might return a singleton instance, a new instance, a mock, a concrete live implementation – all the configurability of Dependency Injection or Service Locator remains.

We then simply apply this aspect to our Consumer class’ properties using an assembly-level attribute;

[assembly: DependencyResolutionAspect(

        AttributeTargetTypes="PostSharpDR.Consumer",

        AttributeTargetMembers="get_*")]

Of course, there are other ways to apply aspects, but this seemed the quickest and simplest sample. Note that I’m filtering for methods that begin with “get_”, which is how .NET compiles the “getter” for a property.

This now means my application code can run as we wanted – assuming the Service Container is suitably initialised. I’ve chosen to do this in code here, but of course this could easily come from configuration;

public class Program

{

    static void Main(string[] args)

    {

        ServiceContainer.Register<IProvider>(new ConcreteProvider());

       

        Consumer consumer = new Consumer();

        consumer.DisplayInfo();

    }

}

As if by magic, our application now works.

One unpleasant implementation detail is that we effectively have a property that does nothing on our Consumer class. In fact, code that assigns to this property will compile, but is counter-intuitive at run time as the value you pass in will never be passed out again from the getter! Therefore, consider the following aspect instead;

[Serializable]

public class DependencyResolutionAspect : OnMethodInvocationAspect

{

    public override void OnInvocation(MethodInvocationEventArgs eventArgs)

    {

        object existingImplementation =

                eventArgs.Delegate.DynamicInvoke(

                        eventArgs.GetArgumentArray());

 

        if (existingImplementation != null)

            eventArgs.ReturnValue = existingImplementation;

        else

            eventArgs.ReturnValue = ServiceContainer.Resolve(

                eventArgs.Delegate.Method.ReturnType);

    }

}

* Note this doesn’t support value types correctly! Again, I’m trying to keep my code simple

Now our aspect will invoke the property that it is intercepting, and return the property’s existing value if it is non-null. If the current value of the property is null, we return an implementation resolved via our Service Container. Of course we could do this in a number of ways (e.g. intercept the set call too, and use a private Boolean field that flags whether a manual set has occurred). This now means we can override the Dependency Resolution behaviour – something that could be really useful for testing if we don’t think we need (or want) to spin up a configured Service Container.

Therefore the following code in a unit test will always use our MockProvider, without changing how any aspects are compiled, and without worrying about whether a Service Container has been initialised or not.

Consumer consumer = new Consumer();

consumer.Provider = new MockProvider();

consumer.DisplayInfo();

Simple huh? The last thing I should mention is that caching the resolved service would probably be worthwhile – because at the moment we’re calling to the service container on every access to the property. This is easy to fix though, so I haven’t bothered for the sake of this post J

Good, Bad, or Ugly?

I think the best way to consider how this stacks up against the alternatives is to compare against what I see as the down-sides to DI and Service Locator;

1.       Responsibility for building up objects. This responsibility has now been pulled out into an Aspect; ideal for AOP, this is a cross-cutting behaviour that I can apply to many methods using configuration statements. My code stays clean, my concerns are separated, and my developers, testers, and architects are all happy (oh, and the flying pigs are too).

2.       Public dependencies. I don’t see any reason why I couldn’t modify the IL for protected and private properties too. We’d just need to be a little careful of this – is a developer really expecting a private object to be resolved by an apparently “external” component? Oh, and I don’t support constructor injection in this post, but I’m sure we could.

3.       Reflection; Doh!! See comments below.

4.       Large object chains; This is perhaps the best bit; as all resolution is done in a “lazy” fashion, only those paths through the object chain get created or resolved. Hey presto, no over-the-top object instantiation, yet no loss of benefits from a Dependency Injection style approach.

 

What don’t I like?

One issue is that really this needs a static weaver to achieve our aims – so many frameworks (Spring, the Enterprise Library, and so on) are out of the picture... for now.

[Edit: The following paragraph is my original content, but it turns out is not a completely accurate picture; be sure to check out Gael's comments below - approx the 27th comment down! Simon] 

Secondly, the fact that my implementation using PostSharp still relies on reflection is a shame, and this is down to how the framework functions; really I’d like to edge this out of the door to maximise the benefits of the pattern, but I don’t fancy writing my own IL parsing cleverness! I haven’t had time to flesh out my ideas around this yet, but if I ever do I’ll be sure to post them!

Conclusion

Well, what do you think? Let the debate begin! I think this is a very simple evolution of Dependency Injection that removes some of the common objections to it – and hence could increase the audience that benefit from what I consider a good pattern to encourage good software design.

Be aware I haven’t used this in a real implementation yet... I’m floating a concept for discussion, so feel free to chip in.