The Dependency Injection Pattern

Today I would you like to write about Dependency Injection pattern. You may already know that the DI pattern eliminates a circular dependency problem in the .NET application. For example, if we have three .NET projects, A, B, and C, The C project has a reference to B, and B has a reference to A. Something like that A-> B-> C. And in that situation, we cannot have references C-> B or B-> A or even C-> A. And then, we can use the Dependency Injection pattern, but the first step is to prepare contracts for each .NET project. Project A has the ClassA class, 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 and 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 ourselves. It is very easy to do that. The only thing 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 projects can be referenced by every class. It is the most important rule contract we can give, but the implementation we must provide. And you probably feel that the Dependency Injection pattern can give you something beneficial. You use the only contract, and DI gives you implementation that can be easy to replace. For example, you can write something like the 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 an 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 the constructor
    public ClassB()
    {
        C = MyFavouriteDI.Resolve<IClassC>();
    }
    public string GetName() {
        return "B" + " and DI = " + C.SayC();
    }
}

And now it is task for you. Implement the 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.

*

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