The code for this step is located on github.

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.

MongoDB Drivers - Wire Protocol Part 2

How drivers talk to MongoDB using the Wire Protocol - Part 2. Continue reading

MongoDB Drivers - Wire Protocol Part 1

Published on December 10, 2013

MongoDB Drivers - Bson

Published on December 02, 2013