Julian Jelfs’ Blog

IoC container is not an uber-factory

Posted in Castle by julianjelfs on July 27, 2009

When I first started seriously using IoC techniques in my application I think I missed the point and I think it is easy to do so. Given that you suddenly have this magical container that you can call Resolve<T> on to get hold of an instance of anything you like, my first temptation was to simply pass around a reference to the container. This is great I thought, because now my classes only need to be dependent on the container.

This is completely the wrong way to think but I never found much guidance to tell me that. Why is it wrong? Firstly because it makes your class dependent on the container and hides the things that it is really dependent on from the consumer code. Secondly, it makes your class impossible to use without using the container. Thirdly, it makes your class difficult to test.

This did not seem obvious to me at the time, but the truth is that you only want to reference your container in one place and that is when you bootstrap the application. For a web application this probably needs to happen in the Application_Start event from Global.asax. From that point on, dependencies are just added to the constructors of your classes and the container resolves those dependencies, but the classes themselves have no knowledge that their dependencies have been resolved by the container. This means that you have a choice whether to use the container or not – your class does not care. So if you wish to instantiate your class directly (in a unit test for example to inject mocks) then you can do so.

I think that one of the reasons I went down the wrong route to start with was because I couldn’t see how to deal with objects whose construction is out of your control. A good example of such an object is a WebForm or a UserControl in Asp.Net. If you are not allowed to reference the container directly in your code, then how do you satisfy your dependencies in such circumstances?

One answer is to set up a layer of indirection between your code and your container. This can take the form of a static Action defined in a location accessible to all of the code that might need to use this technique and also accessible from your bootstrapper. Initially this Action is set to null (or to throw a meaningful exception perhaps). When you initialise your bootstrapper, you can set this Action to perform dependency resolution from the container. So, any time after container initialisation, you can then call this Action from anywhere else in your code and perform container resolution while being insulated form any dependency on the container itself.

So the injection Action might be look something like this:

public static Action<object> InjectProperties;

The bootstrapper might container some code something like this:

Factory.InjectProperties = ContainerExtensions.InjectProperties;

You might also add another level of indirection so that your injection method can be called on any object by adding an extension method to the object type like this:

public static void InjectProperties(this object self)
{
    Factory.InjectProperties(self);
}

And (for example) the UserControl we are injecting dependencies into might then have a parameterless constructor like this:

public MyControl()
{
    this.InjectProperties();
}

In implementing the actual InjectProperties method decisions needs to be made about how to determine which properties the container tries to resolve. One way is to use attributes. You could either define an attribute to flag that a property should be resolved by the container (i.e. an opt-in policy) or you could use the DoNotWire attribute defined in the Castle code base as the basis for an opt-out policy. The following is a simple implementation that would do the job (in this code Container is a static reference to the container itself – this is the only place that you need one apart from the bootstrapper):

public static void InjectProperties(this object self)
{
    if (self == null)
        return;

    var properties = self.GetType().GetProperties();
    foreach (var property in properties)
    {
        if (property.CanWrite == false)
            continue;

        if (property.GetCustomAttributes(typeof(DoNotWireAttribute), true).Length > 0)
            continue;

        if (!Container.HasComponent(property.PropertyType))
            return false; 

        object dependency;
        try
        {
            dependency = Container.Resolve(property.PropertyType);
        }
        catch (Exception e)
        {
            throw new InvalidOperationException("could not resolve component: " + property.PropertyType,e);
        }
        try
        {
            property.SetValue(self, dependency, null);
        }
        catch (Exception e)
        {
            throw new InvalidOperationException("Could not set: " + property, e);
        }
    }
}

This is also a unit test friendly approach as well because you always have the option to override the InjectProperties Action and push mock implementations into the code under test. Or you can just have a unit tests configuration for your container. But successully using mock injection with Castle for unit testing is another post….

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

%d bloggers like this: