Click here to Skip to main content
Email Password   helpLost your password?

Introduction

To write this article I was pushed conversation with one of the Italian software architects, namely with Giorgio Bozio. Idea with ninja is him. The topic for discussion was the question of how to use NInject for implementation Dependency Injection (DI) depending on the context. Now I suggest the decision which I use every day. 

Problem Domain

There are entities in our problem domain: Ninja, SuperNinja, Sword and Shuriken. On the basis of them, we will develop following classes and interfaces:

interface IWeapon
{
    void Use();
} 
class Sword : IWeapon
{
    #region IWeapon Members

    public void Use()
    {
        Console.WriteLine("Sword was used.");
    }

    #endregion
} 
class Shuriken : IWeapon
{
    #region IWeapon Members

    public void Use()
    {
        Console.WriteLine("Shuriken was used.");
    }

    #endregion
} 
class Ninja
{
    [Dependency]
    public IWeapon Weapon { get; set; }
}
class SuperNinja
{
    [Dependency]
    public IWeapon SuperWeapon { get; set; }
}

I'll give some comments to source code. The weapon classes implement common IWeapon interface, but Ninja and SuperNinja classes aren't linked. Many people can object that only ninja is going to make super ninja, and here we must apply such paradigm of OOP as inheritance. But I can object that super ninja can be born only, but ninja can't become a super ninja, and besides inheritance increases coupling in architecture and it are recommended to avoid it. But in this case it isn't important. Further the attention involves attribute Dependency. It points out that the property will be used DI.

Dependency Injection

Now we will consider application DI. For this we will use one of the many frameworks Unity Application Block version 1.2. It’s non-essential, it’s possible to use both StructureMap and Castle Windsor. Simply  Giorgio Bozio had problems with NInject and he had asked to give an example with framework which I used.

The code looks as follows:

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<IWeapon, Sword>();

        var ninja = container.Resolve<Ninja>();
        ninja.Weapon.Use();

        var superNinja = container.Resolve<SuperNinja>();
        superNinja.SuperWeapon.Use();

        Console.ReadKey();
    }
} 

In the beginning the container of dependences is created, and dependences are specified. Here it is obviously set that objects will receive Sword instance by using of IWeapon interface. Further Ninja ? SuperNinja instances are created by means of the container. At creation the properties marked as Dependency, will have values of type Sword. That is there will be DI, to the help which there will be an interface substitution by real objects implementing it.

The code output will be such:

Ninja_1.png

Let's explain result. Ninja and superNinja used the weapon and it had appeared Sword. As followed expect, as other dependences haven't been set by us.

Vulnerable Contextual Dependency Injection

There is one problem: superNinja must have the kind of SuperWeapon. Let's give to him as a weapon Shuriken. Now we will set this dependence, but at once we will notice that only superNinja can have Shuriken. This is Contextual Dependency Injection. In other words the injection is depending on a context of work of object for which it is applied.

There are two most simple ways to make this work.

The first way is creation of the named dependence. The code takes the following form:

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IWeapon, Sword>();
        container.RegisterType<IWeapon, Shuriken>(typeof(SuperNinja).ToString());

        var ninja = container.Resolve<Ninja>();
        ninja.Weapon.Use();

        var superNinja = new SuperNinja();
        superNinja.SuperWeapon = 
            container.Resolve<Shuriken>(typeof(SuperNinja).ToString());
        superNinja.SuperWeapon.Use();

        Console.ReadKey();
    }
}

Note we have set the second dependence for the same interface. This dependence is named. A name it is possible to choose any, but we will choose it with sense - typeof(SuperNinja).ToString(), i.e. dependence for SuperNinja. The code has a little exchanged in place DI, we don't use a default injection, but use an injection with a certain name. It coincides that has been specified in new dependence.

Disadvantage of this way that it is necessary to remember always that the named injection is used and don't forget to point a name at using. It is possible to overcome this disadvantage as follows: always to use the called injections.

Other disadvantage is that creation of object and injection instructions has become complicated. The decision can be same, as well as at the previous disadvantage.

That result which we also achieved:

Ninja_2.png

The second way is creation of the nested container. The code:

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IWeapon, Sword>();

        var childContainer = container.CreateChildContainer();
        childContainer.RegisterType<IWeapon, Shuriken>();

        var ninja = container.Resolve<Ninja>();
        ninja.Weapon.Use();

        var superNinja = childContainer.Resolve<SuperNinja>();
        superNinja.SuperWeapon.Use();

        Console.ReadKey();
    }
}

Following changes have been made: the nested container of dependences has been created and the way of setting of an injection is changed. From a code it is visible that the nested container redefines dependence of the parent container.

Disadvantage of this way that it is necessary to set other container for the creation of dependences and don't forget it to use. The decision consists in moving of code of creation the nested container as it is possible more close to a place of its direct using.

Let's bring a certain intermediate result. It was offered two ways of the decision of a problem with contextual DI. They have the advantages and the disadvantages. It is necessary as to underline that disadvantages can be smoothed by application of a configuration file. All dependences which are set in source code, they can be set as declarative. But there is one fundamental disadvantages – injection setting isn't always set only for SuperNinja.

We can make so, for example:

var ninja = container.Resolve<Ninja>(typeof(SuperNinja).ToString());
ninja.Weapon.Use(); 

 Apparently ninja used of superNinja weapon, and it was already dangerous. We want the way of the setting of a special injection only for SuperNinja class. And such way is.

Protected Contextual Dependency Injection 

We need cofigurate the container by addition of new dependence:

 container.RegisterType<SuperNinja>(
     new InjectionProperty("SuperWeapon", new Shuriken())); 

Here all is simple. Particularly for SuperNinja type it is underlined that at an injection in SuperWeapon property, it'll receive Shuriken type. We start the program and we receive result similar to the previous. But also here we are expected by a problem. Let's call one more SuperNinja and we'll ask him where he takes the weapon. To be exact the question will sound so: “Listen, guy, you borrowed this SuperWeapon at your friend SuperNinja?”

We will express this question in code:

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IWeapon, Sword>();

        container.RegisterType<SuperNinja>(
            new InjectionProperty("SuperWeapon", new Shuriken()));

        var ninja = container.Resolve<Ninja>();
        ninja.Weapon.Use();

        var superNinja = container.Resolve<SuperNinja>();
        superNinja.SuperWeapon.Use();

        var superNinja2 = container.Resolve<SuperNinja>();

        Console.WriteLine(
            ReferenceEquals(superNinja.SuperWeapon, superNinja2.SuperWeapon));

        Console.ReadKey();
    }
} 

And he will answer us:

Ninja_3.png

I.e. it turns out that he has all the same borrowed the weapon at the friend. Speaking to the programming language, references on SuperWeapon the first and the second SuperNinja coincide. Well, in it there is nothing bad, such mutual aid between friends is complimented. But let's try make so that everyone ninja had the SuperWeapon. How? At first sight we can be helped by ResolvedParameter class. It is intended just for this purpose. Unique restriction which can stop us, it is that the given class generates object on the basis of the container of injections to which configuration it is applied. As consequence, for our IWeapon interface, it will be again found Sword. The truth it is possible to try to use the second constructor of ResolvedParameter class, but it is required to transfer a dependence name.

The code will assume the following:

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IWeapon, Sword>();
        container.RegisterType<IWeapon, Shuriken>(typeof(SuperNinja).ToString());

        container.RegisterType<SuperNinja>(
            new InjectionProperty(
                "SuperWeapon",
                new ResolvedParameter<IWeapon>(typeof(SuperNinja).ToString())));

        var ninja = container.Resolve<Ninja>();
        ninja.Weapon.Use();

        var superNinja = container.Resolve<SuperNinja>();
        superNinja.SuperWeapon.Use();

        var superNinja2 = container.Resolve<SuperNinja>();

        Console.WriteLine(
            ReferenceEquals(superNinja.SuperWeapon, superNinja2.SuperWeapon));

        Console.ReadKey();
    }
} 

Apparently from a source code, there is a named dependence again. But one of old disadvantage, namely inconvenient creation of objects, is already irrelevant.

We have reached our result: 

Ninja_4.png

It was possible to stop, but our code still had a number of disadvantages. We will list them: the code is depended with string name of property; Ninja class also has access to dependence of SuperNinja class (a consequence from the second disadvantage of the named dependence). We will try to eliminate these disadvantages by introduction of additional level abstraction.

public static class UnityContainerHelper
{
    private static IDictionary<Type, IUnityContainer> Container { get; set; }

    public static IUnityContainer RegisterType<TFrom, TTo, TFor>(
        this IUnityContainer container, 
        params InjectionMember[] injectionMembers)
        where TTo : TFrom
    {
        if (Container == null)
        {
            Container = new Dictionary<Type, IUnityContainer>();
        }

        var key = typeof(TFor);

        if (Container.ContainsKey(key) == false)
        {
            Container[key] = container.CreateChildContainer();
        }

        return Container[key].RegisterType<TFrom, TTo>();
    }

    public static T ResolveType<T>(this IUnityContainer container)
    {
        var key = typeof(T);
        return 
            Container.ContainsKey(key) ?
            Container[key].Resolve<T>() :
            container.Resolve<T>();
    }
}

We created a service class with pair extension methods. We will explain their work. The first method extends registration of dependences in IUnityContainer. At its using it is required to set explicitly type for which dependence makes sense. The given type is a key in the dictionary of dependences, and value is the container which redefines parent dependence. The second method extends a method of the resolving of dependences. If the object type for which there is an injection, is available in the dictionary the redefined dependence is applied. Otherwise, dependence resolves with help of parent container. It is necessary to notice that the code support only one parent container. It has been made specially, because I don't overload a program code of unnecessary details. Implementation is easy for one more containers and you'll think up yourself.

The program code became simpler:

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IWeapon, Sword>();
        container.RegisterType<IWeapon, Shuriken, SuperNinja>();

        var ninja = container.ResolveType<Ninja>();
        ninja.Weapon.Use();

        var superNinja = container.ResolveType<SuperNinja>();
        superNinja.SuperWeapon.Use();

        var superNinja2 = container.ResolveType<SuperNinja>();

        Console.WriteLine(
            ReferenceEquals(superNinja.SuperWeapon, superNinja2.SuperWeapon));

        Console.ReadKey();
    }
}

Note that instead of Resolve method we use our extending ResolveType method. In the rest the code is transparent enough.

Conclusion

I hope that I have answered questions Giorgio Bozio and my readers. Welcome to comments.

Thank you, Oleg Smirnov.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralContextual Dependency Injection is useful
GWSyZyGy
7:34 16 Dec '08  
I've resorted to writing my own contextual dependency injection because the available frameworks don't do it at all or do it too clumsily, as you point out in your article.

For those wondering WHY CDI is useful, let me offer how I use it. Most commonly, I use it to get the appropriate GUI control for whatever business object need to display.

For example, I may have an Employee business object that has an "asssociated" EmployeeListView for displaying a set of Employee objects properly (and maybe an EmployeeDropDownSelector, etc. etc.). Without CDI, to create a window for displaying and possibly editing Employees, you generally code up an EmployeesView form that has the EmployeeListView on it and whatnot and so forth.

However, if you have CDI, you can (and I did Smile ) create a generic SelectionView form that given a businessobject of T can resolve at runtime the correct IListView to plop on the form. One window, unlimited variations. The form no longer needs to know or care what specific business object type its mucking around with. "Standard" DI can give easily you an OracleEmployeeDAL when you ask for a IEmployeeDAL. Or a FancyGlassButton for any Button requests. Not so good at handing you an EmployeeListView when you ask for an IListView for an Employee, or a DepartmentListView for a Department, or even another EmployeeListView for a Manager (which inherits from Employee) .. assuming there is no ManagerListView registered.

Thanks for putting this article out,

GeneralService locator [modified]
Giorgio Bozio
11:56 2 Dec '08  
Hi Oleg,
your implementation is interesting but it's not fitting the needs of my architecture.

I really wouldn't want the client code to know details about what implementation of the dal interfaces to instantiate.
The business logic code needs to instantiate an object implementing the interface without knowing the concrete implementation. This object should provide the service of creating, managing and disposing a database session, without knowing the details of how this services are provided.

In fact I found out lately that this way of breaking dependency is called by Martin Fowler the Service Locator Pattern.

It is possible to obtain this result with NInject but I couldn't get to work the contextual injection.

Cheers,
Giorgio

modified on Tuesday, December 2, 2008 5:15 PM


Last Updated 30 Nov 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010