The Dependency Injection Pattern

Today I would you like to write about Dependency Injection pattern. You may already know that the DI pattern eliminate a circular dependency problem in .NET application. For example if we have three .NET projects A, B and C. C has reference to B and B has reference to A. Something like that A->B->C. And in that situation we cannot have references C->B or B->A or event C->A. And then we can use Dependency Injection pattern, but first step is to prepare contracts for each .NET projects. The project A has the ClassA class, the project B has the ClassB class and so on. So we can prepare project ABC.Contract with the IClassA, the IClassB and the IClassC interfaces. Classes in projects should implement that interfaces (It is very easy to extract interface from the class in the Visual Studio IDE).

So now we have four projects A, B, C nad ABC.Contract and we are ready to implement the DI pattern. We can use for example the ObjectBuilder from Codeplex or maybe the Windsor from the Castle project site or maybe the Unity from Enterprise Library or event the PostSharp or MEF. But imagine that we want to implement the Dependency Injection Pattern by self. It is very easy to do that. The only think we need is class where we can store instances for particular interfaces (called also as contracts if you want that terminology).

Let see what we get now.

// The A .NET project
public class ClassA : IClassA
{
    public string GetShortName()
    {
        return "A";
    }
}
// The B .NET project
public class ClassB : IClassB
{
    public string GetName() {
        return "B";
    }
}
// The C .NET project
public class ClassC : IClassC
{
    public string SayC()
    {
        return "C";
    }
}
// The ABC.Contract .NET project
public interface IClassA {
    string GetShortName();
}

public interface IClassB {
    string GetName();
}

public interface IClassC {
    string SayC();
}

Most important rule for memorize. The ABC. Contract project can be referenced by every class. It is most important rule contract we can give but implementation we must provide. And you probably feel that Dependency Injection pattern can give you something very useful, You use the only contract and DI gives you implementation that can be easy to replace. For example, you can write something like below.

public class Program {
    static Program()
    {
        MyFavouriteDI.Register<IClassC>(new ClassC());
        MyFavouriteDI.Register<IClassB>(new ClassB());
        MyFavouriteDI.Register<IClassA>(new ClassA());
    }

    static void Main(string[] args)
    {
        IClassA a = MyFavouriteDI.Resolve<IClassA>();
        IClassB b = MyFavouriteDI.Resolve<IClassB>();
        IClassC c = MyFavouriteDI.Resolve<IClassC>();

        Console.WriteLine("a.GetShortName() = {0}", a.GetShortName());
        Console.WriteLine("b.GetName() = {0}", b.GetName());
        Console.WriteLine("c.SayC() = {0}", c.SayC());
    }
}

Or maybe better example, we can change the ClassA like below. This is example of lazy injected dependency.

// The A .NET project
public class ClassA : IClassA
{
    private IClassB BI;

    public string GetShortName()
    {
        return "A" + " and DI = " + B.GetName();
    }

    // The dependency injection by property
    public IClassB B
    {
        get { return BI ?? (BI = MyFavouriteDI.Resolve<IClassB>()); }
    }
}

Or maybe in different way we can change ClassB like is shown below. This is example of early injected dependency.

// The B .NET project
public class ClassB : IClassB
{
    private readonly IClassC C;

    // The dependency injection by constructor
    public ClassB()
    {
        C = MyFavouriteDI.Resolve<IClassC>();
    }

    public string GetName() {
        return "B" + " and DI = " + C.SayC();
    }
}

And now it is task for you. Implement body of Register and Resolve methods in the MyFavouriteDI class.

public static class MyFavouriteDI
{
    Dictionary<Type, object> Instances = new Dictionary<Type, object>();

    public static bool Register<T>(object instance)
    {
        // Register instance.
    }

    public static T Resolve<T>()
    {
        // Find instance.
    }
}

You may also answer for questions:

1) How to implement this DI class not static?

2) What is the best pattern for that changes?

3) How to enhance the MyFavouriteDI with keys for different implementations of the same interface?

4) Where we can store that keys?

5) Why DI in lazy model is better then early one?

6) Did you know why I registered instances in desc order in the Program class?

Best regards and enjoy,

P ;).

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.