Build Your Own IoC Container User Group Recording

So, apparently the talk I gave on the Build Your Own IoC Container series was recorded and posted online. Being one of my first talks, I thought it went well. If I’d known how they were recording, I would have done a few things differently like repeat the questions that were asked, but overall it went pretty well.

There is no sound for about 3 minutes and then I get interupted by the guys running the group to announce some things, but after we get through that, it is pretty smooth.

http://usergroup.tv/videos/build-you-own-ioc-container

Hope you enjoy…

Advertisements

Building an IoC Container – Cyclic Dependencies

The code for this step is located here.

We just finished doing a small refactoring to introduce a ResolutionContext class. This refactoring was necessary to allow us to handle cyclic dependencies. Below is a test that will fail right now with a StackOverflowException because the resolver is going in circles.

public class when_resolving_a_type_with_cyclice_dependencies : ContainerSpecBase
{
    static Exception _ex;

    Because of = () =>
        _ex = Catch.Exception(() => _container.Resolve(typeof(DummyService)));

    It should_throw_an_exception = () =>
        _ex.ShouldNotBeNull();

    private class DummyService
    {
        public DummyService(DepA a)
        { }
    }

    private class DepA
    {
        public DepA(DummyService s)
        { }
    }
}

Technically, a StackOverflowException would get thrown and caught. However, this type of exception is going to take out the whole app and the test runner won’t be able to complete. Regardless, it shouldn’t take a minute to take out the heap and this should fail almost instaneously.

With a slight modification to our ResolutionContext class, we can track whether or not a cycle exists in the resoluation chain and abort early. There are two methods that need to be modified.

public object ResolveDependency(Type type)
{
    var registration = _registrationFinder(type);
    var context = new ResolutionContext(registration, _registrationFinder);
    context.SetParent(this);
    return context.GetInstance();
}

private void SetParent(ResolutionContext parent)
{
    _parent = parent;
    while (parent != null)
    {
        if (ReferenceEquals(Registration, parent.Registration))
            throw new Exception("Cycles found");

        parent = parent._parent;
    }
}

We begin by allowing the ResolutionContext to track it’s parent resolution context. This, as you can see in the SetParent method, will allow us to check each parent and see if we have tried to resolve a given type already. Other than that, nothing special is going on and everything else still works correctly.

At this point, we are at the end of the Building an IoC Container series. I hope you have learned a little more about how the internals of your favorite containers work and, even more so, that there isn’t a lot of magic going on. This is something you can explain to your peers or mentees and hopefully allow the use of IoC to gain an acceptance in area that has once been off-limits because it was a “black-box”. Be sure to leave me a comment if you have any questions or anything else you’d like to have done to our little IoC container.

Building an IoC Container – Refactoring

The code for this step is located here.

In the last post, we added support for singleton and transient lifetimes. But the last couple of posts have made our syntax look a bit unwieldy and is somewhat limitting when looking towards the future, primary when needing to detect cycles in the resolution chain. So today, we are going to refactor our code by introducing a new class ResolutionContext. This will get created everytime a Resolve call is made. There isn’t a lot to say without looking at the code, so below is the ResolutionContext class.

public class ResolutionContext
{
    private readonly Func _resolver;

    public Registration Registration { get; private set; }

    public ResolutionContext(Registration registration, Func resolver)
    {
        Registration = registration;
        _resolver = resolver;
    }

    public object Activate()
    {
        return Registration.Activator.Activate(this);
    }

    public object GetInstance()
    {
        return Registration.Lifetime.GetInstance(this);
    }

    public object ResolveDependency(Type type)
    {
        return _resolver(type);
    }

    public T ResolveDependency()
    {
        return (T)ResolveDependency(typeof(T));
    }
}

Nothing in this is really that special. The Activate method and the GetInstance method are simply here to hide away the details so the caller doesn’t need to dot through the Registration so much (Law of Demeter). The Funcis still here, but this is where it stops. Shown below, our IActivator and ILifetime interfaces now take a ResolutionContext instead of the delegates.

public interface IActivator
{
    object Activate(ResolutionContext context);
}

public interface ILifetime
{
    object GetInstance(ResolutionContext context);
}

Now, they look almost exactly the same, so, as we discussed in the last post, the difference is purely semantic. Activators construct things and Lifetimes manage them.

Finally, no new tests have been added, but a number have changed due to this refactoring. I’d advise you to check out the full source and look it over yourself. In our next post, we’ll be handling cyclic dependencies now that we have an encapsulated ResolutionContext to track calls.

Building an IoC Container – Adding Lifetimes

The code for this step is located here.

We left off the previous post with the need to support different lifetime models such as Singleton, Transient, or per Http Request. After our last refactoring, this is actually a fairly simple step if we follow the single responsiblity principle and define the roles each of our abstractions play.

Currently, we only have 1 abstraction which is around activation. It would be fairly simple to use activators to handle lifetime as well, but things will quickly become complex if we go this route. Therefore, we will define an activators job as activating an object. In other words, it’s only job is to construct an object using whatever means it wants, but it should never store the instance of an object in order to satisfy a lifetime requirement.

In order to manage lifetimes, we will introduce a second abstract called an ILifetime. It’s sole job is to manage the lifetime of an activated object. It can(and will) use an activator to get an instance of an object, but it will never construct one itself.

By keeping these two ideas seperate, it makes this a fairly trivial addition. Below are the two tests for this functionality, one for transient and one for singletons.

public class when_resolving_a_transient_type_multiple_times : ContainerSpecBase
{
    static object _result1;
    static object _result2;

    Because of = () =>
    {
        _result1 = _container.Resolve(typeof(DummyService));
        _result2 = _container.Resolve(typeof(DummyService));
    };

    It should_not_return_the_same_instances = () =>
    {
        _result1.ShouldNotBeTheSameAs(_result2);
    };

    private class DummyService { }
}

public class when_resolving_a_singleton_type_multiple_times : ContainerSpecBase
{
    static object _result1;
    static object _result2;

    Establish context = () =>
        _container.Register().Singleton();

    Because of = () =>
    {
        _result1 = _container.Resolve(typeof(DummyService));
        _result2 = _container.Resolve(typeof(DummyService));
    };

    It should_return_the_same_instances = () =>
    {
        _result1.ShouldBeTheSameAs(_result2);
    };

    private class DummyService { }
}

You see above that we are making transient the default lifetime and adding a method to set a singleton lifetime.

public interface ILifetime
{
    object GetInstance(Type type, IActivator activator, Func resolver);
}

public class TransientLifetime : ILifetime
{
    public object GetInstance(Type type, IActivator activator, Func resolver)
    {
        return activator.Activate(type, resolver);
    }
}

public class SingletonLifetime : ILifetime
{
    private object _instance;

    public object GetInstance(Type type, IActivator activator, Func resolver)
    {
        if (_instance == null)
            _instance = activator.Activate(type, resolver);
        return _instance;
    }
}

So, an ILifetime has a single method that takes the type, the activator, and the resolver. We are going to clean this up in the next installment, but regardless, these implementations are still relatively simple.

The TransientLifetime is basically a pass-through on the way to the activator. It doesn’t store anything, so it has no need to do any interception. The SingletonLifetime, however, only activates an object once, stores the instance, and then returns that instance everytime. I haven’t included threading in here, but a simple lock would suffice for most cases.

We need to add a Lifetime and a Singleton method onto our Registration class:

public class Registration
{
    //other properties

    public ILifetime Lifetime { get; private set; }

    public Registration(Type concreteType)
    {
        ConcreteType = concreteType;
        Activator = new ReflectionActivator();
        Lifetime = new TransientLifetime();

        Aliases = new HashSet();
        Aliases.Add(concreteType);
    }

    //other methods

    public Registration Singleton()
    {
        Lifetime = new SingletonLifetime();
        return this;
    }
}

Finally, we just need to change the Resolve method in our Container class to use the Lifetime as opposed to the Activator and we are all done.

public object Resolve(Type type)
{
    var registration = FindRegistration(type);
    return registration.Lifetime.GetInstance(registration.ConcreteType, registration.Activator, Resolve);
}

In our next post, we’ll do some refactoring ultimately to support handling cyclic dependencies. A by product of this is a better coded container. See you then…

Building an IoC Container–Resolving Abstractions

The code for this step is located here.

From our previous post, we added the ability to register dependencies with dependencies that couldn’t be resolved by the container.  These would be dependencies like primitives or abstractions like interfaces.  In this post, we are going to solve our inability to resolve an abstraction by adding aliases to the Registration class.

Below is our test for this functionality:

public class when_resolving_a_type_by_its_alias : ContainerSpecBase
{
    static object _result;

    Establish context = () =>
        _container.Register<DummyService>().As<IDummyService>();

    Because of = () =>
        _result = _container.Resolve(typeof(IDummyService));

    It should_not_return_null = () =>
        _result.ShouldNotBeNull();

    It should_return_an_instance_of_the_requested_type = () =>
        _result.ShouldBeOfType<DummyService>();

    private interface IDummyService { }
    private class DummyService : IDummyService { }
}

Above, the only difference from an API standpoint is the addition of the “As” method. This is basically telling the container that DummyService should be returned when IDummyService is requested.

So, the first change we’ll make is on the Registration class. We’ll add a property called Aliases. Aliases will include all the types that should resolve to the same concrete class including the concrete version. So, Register().As().As() will resolve when any of the types ISomeServiceA, ISomeServiceB, or SomeService is requested. Our new registration class looks like this:

public class Registration
{
    public Type ConcreteType { get; private set; }

    public IActivator Activator { get; private set; }

    public ISet<Type> Aliases { get; private set; }

    public Registration(Type concreteType)
    {
        ConcreteType = concreteType;
        Activator = new ReflectionActivator();

        Aliases = new HashSet<Type>();
        Aliases.Add(concreteType);
    }

    public Registration ActivateWith(IActivator activator)
    {
        Activator = activator;
        return this;
    }

    public Registration ActivateWith(Func<Type, Func<Type, object>, object> activator)
    {
        Activator = new DelegateActivator(activator);
        return this;
    }

    public Registration As<T>()
    {
        Aliases.Add(typeof(T));
        return this;
    }
}

The only other change we need to make is in the container where we are trying to find a registration.

private Registration FindRegistration(Type type)
{
    var registration = _registrations.FirstOrDefault(r => r.Aliases.Contains(type));
    if (registration == null)
        registration = Register(type);

    return registration;
}

That’s it! All the tests should still pass and all is good with the world. In the next post, we are going to talk about lifetimes (Singleton, Transient, PerRequest, etc…) and how to add them into our container.

Stay Tuned.

Building an IoC Container–Resolving Types with Unresolvable Dependencies

The code for this step is located here.

From our previous post, we are able to resolve types with dependencies that they themselves can be resolved.  We all know from experience that this is hardly ever true without some help.  For instance, a type that takes an integer in its constructor would be impossible to resolve in our current state.  To combat this, we are going to create something called an activator.  It’s entire purpose is to, given a type, give back an instance of that type through construction.  The interface is defined below:

public interface IActivator
{
    object Activate(Type type, Func<Type, object> resolver);
}

Nothing special here, but what is special is the abstraction we are creating between the activation of an instance and the implementation.  Our first implementation will be to refactor the current activation code embedded in the Resolve method of the container into a new activator called a ReflectionActivator.

public class ReflectionActivator : IActivator
{
    public object Activate(Type type, Func<Type, object> resolver)
    {
        var ctor = type.GetConstructors()
                       .OrderByDescending(c => c.GetParameters().Length)
                       .First();

        var parameters = ctor.GetParameters();
        var args = new object[parameters.Length];
        for (int i = 0; i < args.Length; i++)
            args[i] = resolver(parameters[i].ParameterType);

        return ctor.Invoke(args);
    }
}

With the exception of the resolver Func that is passed in and its usage, this code is identical to the Resolve method.  The resolver argument has the same signature as the Resolve method, thereby allowing us to perform the same recursion we were using previously.  We can now replace the existing code in Resolve with the below method:

public object Resolve(Type type)
{
    var activator = new ReflectionActivator();
    return activator.Activate(type, Resolve);
}

At this point, all our existing tests should still pass (because we really haven’t done anything).  Let’s go ahead and refactor some more allowing different types to be registered with their own settings.  This is the final refactoring before we can solve the original stated problem.

Below is the Registration class.  It has a property called ConcreteType.  I’m naming it that because I know some things about the future that you don’t, but regardless, it holds the actual type that can be constructed.

public class Registration
{
    public Type ConcreteType { get; private set; }

    public IActivator Activator { get; private set; }

    public Registration(Type concreteType)
    {
        ConcreteType = concreteType;
        Activator = new ReflectionActivator();
    }

    public Registration ActivateWith(IActivator activator)
    {
        Activator = activator;
        return this;
    }

    public Registration ActivateWith(Func<Type, Func<Type, object>, object> activator)
    {
        Activator = new DelegateActivator(activator);
        return this;
    }
}

The take away from the class above is that we have a ConcreteType that has an instance of IActivator associated with it.  Therefore, an unresolvable ConcreteType can be activated differently than one that is resolvable.  For instance, the implementation of the IActivator that solves our original problem is called the DelegateActivator.

public class DelegateActivator : IActivator
{
    private readonly Func<Type, Func<Type, object>, object> _activator;

    public DelegateActivator(Func<Type, Func<Type, object>, object> activator)
    {
        _activator = activator;
    }

    public object Activate(Type type, Func<Type, object> resolver)
    {
        return _activator(type, resolver);
    }
}

Yes, that is a Func that takes a Func as an argument.  This will get cleared up in a future refactoring, but for now, this is actually quite simple.  The nested Func argument is the Resolve method (give me a type, and I’ll give you back an instance).  So, that last thing to do is to refactor the Container class to use the Registration class and the Activators.

public class Container
{
    private List<Registration> _registrations = new List<Registration>();

    public Registration Register(Type type)
    {
        var registration = new Registration(type);
        _registrations.Add(registration);
        return registration;
    }

    public Registration Register<T>()
    {
        return Register(typeof(T));
    }

    public object Resolve(Type type)
    {
        var registration = FindRegistration(type);
        return registration.Activator.Activate(type, Resolve);
    }

    public T Resolve<T>()
    {
        return (T)Resolve(typeof(T));
    }

    private Registration FindRegistration(Type type)
    {
        var registration = _registrations.FirstOrDefault(r => r.ConcreteType == type);
        if (registration == null)
            registration = Register(type);

        return registration;
    }
}

Just to note, we are allowing the resolution of types that have not been explicitly registered with the container.  I believe that some other notable IoC container authors disagree with this practice, namely Krzysztof Koźmic and Nicolas Blumhardt.  Their reasoning is that without explicit configuration, it is easy for the container to misbehave.  I say, have enough tests so that doesn’t become an issue.  Regardless, this is how it is coded and if you disagree, rip out that part and throw an exception.

One other thing to note is that we are not threadsafe. This would be relatively simple to add using the new concurrent collection types in .NET 4.0. I’ll leave that to you to play around with.

Below is the new test we have added for this batch of functionality:

public class when_resolving_a_type_with_unresolvable_dependencies : ContainerSpecBase
{
    static object _result;

    Establish context = () =>
        _container.Register<DummyService>()
            .ActivateWith((t, r) => new DummyService(9, (DepA)r(typeof(DepA))));

    Because of = () =>
        _result = _container.Resolve(typeof(DummyService));

    It should_not_return_null = () =>
        _result.ShouldNotBeNull();

    It should_return_an_instance_of_the_requested_type = () =>
        _result.ShouldBeOfType<DummyService>();

    private class DummyService
    {
        public DummyService(int i, DepA a)
        { }
        }

    private class DepA { }
}

Like I said above, a little ugly with that ActivateWith call. It is saying to use 9 for the integer and resolve DepA from the container.

In the next post, we’ll get into how to handle resolving IDummyService, which is basically the whole point of this exercise. Stay tuned…

Building an IoC Container – Resolving Types with Dependencies

The code for this step is located here.

In the previous post, we created our first test and our container implementation.  It is very simple and only resolves types with default constructors. In the installment, we’ll take this a step further and resolve types by discovering it’s constructors parameters and resolving them as well.

But first, let’s write a test to show us exactly what we are trying to do.

public class when_resolving_a_type_with_dependencies : ContainerSpecBase
{
    static DummyService _result;

    Because of = () =>
        _result = (DummyService)_container.Resolve(typeof(DummyService));

    It should_not_return_null = () =>
        _result.ShouldNotBeNull();

    It should_return_an_instance_of_the_requested_type = () =>
        _result.ShouldBeOfType<DummyService>();

    It should_return_an_instance_with_the_dependency_created = () =>
        _result.A.ShouldNotBeNull();

    private class DummyService
    {
        public DepA A { get; private set; }

        public DummyService(DepA a)
        {
            A = a;
        }
    }

    private class DepA { }
}

As you can see, when constructing DummyService, we must provide it with an instance of DepA.  Currently, this test will fail because our current implementation assumes a default constructor exists.  Let’s remove that assumption.

public class Container
{
    public object Resolve(Type type)
    {
        var ctor = type.GetConstructors()
            .OrderByDescending(c => c.GetParameters().Length)
            .First();

        var parameters = ctor.GetParameters();
        var args = new object[parameters.Length];
        for (int i = 0; i < args.Length; i++)
            args[i] = Resolve(parameters[i].ParameterType);

        return ctor.Invoke(args);
    }

    public T Resolve<T>()
    {
        return (T)Resolve(typeof(T));
    }
}

Simpler than you thought, huh?  Let’s walk through this real quick.  First, we get the constructor that has the most parameters.  If we wanted, this could be published as an extensibility point to allow a consumer to alter the strategy of how to select a constructor.  However, this fits our needs just fine.  After this, we simply iterate through all the parameters of the constructor and recursively call Resolve for each and store the result in the args array.  Finally, we invoke the constructor with all the args.

In the next post, we’ll discuss how to deal with types that can’t be resolved using the above method.

Building an IoC Container – Resolving Types without Dependencies

The code for this step is located here.

As noted in the introduction, we are going to take this in steps and go in a test first manner.  So, let’s write our first test.

public class when_resolving_a_type_with_zero_dependencies : ContainerSpecBase
{
    static object _result;

    Because of = () =>
        _result = _container.Resolve(typeof(DummyService));

    It should_not_return_null = () =>
        _result.ShouldNotBeNull();

    It should_return_an_instance_of_the_requested_type = () =>
        _result.ShouldBeOfType();

    private class DummyService { }
}

If you haven’t used Machine.Specifications, this may seem like odd syntax.  But what I like about it is that it is easy to see what is going on when the container is resolving a type with zero dependencies.  First,  the container shouldn’t return null and second, the container should return an instance of the requested type.

Now that we have a test, we are going to start coding the implementation.  We’ll start with the simplest thing that could possibly work here.

public class Container
{
    public object Resolve(Type type)
    {
        return Activator.CreateInstance(type);
    }

    public T Resolve()
    {
        return (T)Resolve(typeof(T));
    }
}

Nothing special, and nothing that you couldn’t have figured out on your own.  In the next post, we’ll see how to handle this when the requested type has dependencies.

Building An IoC Container – Series Introduction

As I have moved into a consulting role, I have become more and more surprised with the number of .NET developers who have not heard of Dependency Injection or Inversion of Control.  Talking to different people about the concept is met with a few reactions.  While I can’t do anything about the people who simply don’t care, there are two groups of people that I can help.

I began giving talks entitled “Build Your Own IoC Container” at local events here in Dallas.  This isn’t because I’m a proponent of actually building your own and using it production, but rather as a way to educate the two different groups of people.  (Just to reiterate; please don’t build your own for production.)

The first group are those who simply don’t know about IoC.  The talk (and this series) simply start with a blank slate and begin building in a test-driven(sort of) manner.  I’ll use Machine.Specifications as it makes clearer the intent (plus, I just really like it).  I’ve found that by removing the “black-box”, there is more understanding and adoption.

The second group are those who already know about how containers work, but don’t know how to explain them to others.  I was once in this place and needed to figure out how to talk about it with someone who didn’t know.  So, I did what I always do when I don’t understand something; I build it.  This helped me understand enough of the insides to answer the more difficult questions.  Hopefully, by building one together, you and I will gain a greater understanding of the basics of a container.

At the end of the series, we’ll have a fully functional container that supports pluggable lifetimes, multiple registrations for a type, factories, and cyclic dependencies.  There are 218 lines and 1 file.

This series will be in 7 parts:

Extension Methods And Null Objects

Sebastien has posted about his use of extension methods on null objects.  I have seen other code with extension methods for IsNull and I have a fundamental disagreement with these types of extension methods.

Extensions methods are syntactic sugar around a static method taking and instance as its first argument.  In C# and VB.NET, they basically make the method feel like an instance method during development, and the compiler takes care of generating the appropriate IL for calling the static method (which is what it really is).

So, what is my problem?  You can’t call an instance method when there is no instance.  Let’s assume I have an instance method defined for all objects:

public static bool IsNull(this object o) { return o == null; }

object o = null;
o.GetHashCode(); //throws an exception.
o.IsNull(); //does not throw an exception.

It doesn’t throw because it is really just a static method underneath being purported to the developer as an instance method.  I think this is a mistake made by the compiler for allowing this, but since it does, it is now an abuse of the language feature.