Saturday, March 28, 2015

Microsoft Unity IoC Container

SOLID

Because we’re following SOLID code design we should have:
  • Small classes
  • Concrete classes that implement interfaces (with very few exceptions)
  • Any interactions with a concrete class should be done using the interface
  • Classes that other classes depend on should be injected into them during instantiation (preferably using the constructor)

A natural outgrowth of these rules is IoC.

IoC

IoC stands for Inversion of Control. It’s a byproduct of the Dependency Inversion principal. Instead of classes higher in the dependency chain determining what concretion of a class they should be using, a separate context determines which concretions get used.
This is confusing so let’s take a look at some sample code.

public class A
{
    public void LogIt()
    {
        var log = new Log();
        log.LogMe("I'm not testable!");
    }
}

public class Log
{
    public void LogMe(string message)
    {
        Console.WriteLine(message);
    }
}

In this example A creates an instance of Log and calls the LogMe method. A is Higher on the dependency chain and determines which class to use to call the LogMe method.

This is bad for a few reasons:
  • I can’t test A desperately from Log. For larger classes and more dependencies this makes unit testing impossible. As the different possibilities pile up (code paths or combinations) testing become exponential.
  • If I want to change A's use of Log but preserve Log in it's current form (if other classes use Log) I am forced to modify A as well. This is especially frustrating if I want to call LogMe still.

Let’s take a look at a more maintainable code base:

public class A : IA
{
    private readonly ILog _log;
 
    public A(ILog log)
    {
        _log = log;
    }

    public void LogIt()
    {
        _log.LogMe("A is now testable!");
    }
}

public interface IA
{
    void LogIt();
}

public class Log : ILog
{
    public void LogMe(string message)
    {
        Console.WriteLine(message);
    }
}
 
public interface ILog
{
    void LogMe(string message);
}

The above example's code has increased some because we inject a concrete instance of Log as an interface ILog into A. A is now not in charge of determining what concrete implementation of ILog is used. We've also created interfaces for both A and Log.

This is:
  • Testable: I can test A and Log separately.
  • Swappable: If I need to I can specify a different concretion of ILog with no modification to A.

Notice that the concreate implementation of ILog is injected into A’s constructor and the interface ILog is private inside of A. This is called Constructor Injection.

There’s also a concept called Property Injection where a class exposes its dependencies as public properties. This is not a good idea as other classes could change your dependencies.

Enter MS Unity IoC Container

This leaves us with a problem. How do we organize and assemble all these classes together? In particular, if we have lots of small classes that call each other there’s going to be a lot of work done up front.

You can manually assemble the classes when your application first starts but it quickly becomes chaos and hard to read.

How do we avoid the mess that manually assembling dependencies together creates? Inversion of Control (IoC) Containers to the rescue.

IoC Containers provide a framework for organizing and managing dependencies inside your application. We will be using Microsoft Unity IoC Container in this example to assemble our dependency chain.

Let’s take a look at some code:

public static void AssembleDependencies()
{
    var unityContainer = new UnityContainer();

    unityContainer.RegisterInstance<ILog>(new Log());
    
    unityContainer.RegisterType<IA, A>(
        new InjectionConstructor(
            container.Resolve<ILog>()
        )
    );
}

RegisterType tells Unity to create a new instance of the concrete class anytime one is needed. In our example if A get's used multiple times Unity will create new instances each time.

RegisterIntance tells Unity to create and use only one instance for a specific lifetime. More often then not you will only need one instance of a logger (Log) for your application so here RegisterInstance only creates one.

This is kind of like the difference between using a Factory design pattern and a Singleton design pattern:
  • Factory is a creational pattern which uses factory methods to deal with the problem of creating objects without specifying the exact class of object that will be created.
  • Singleton is a design pattern that restricts the instantiation of a class to one object.

RegisterType is a kind of Factory pattern with more capability. You use it when a new instance of a class is needed each time that class is used.

RegisterInstance is a kind of Singleton pattern with more capability. You use it when you only want one instance of a class in the whole application. However, you can also tell Unity when you want to expire the class and create a new one as well.

unityContainer.RegisterInstance<ILog>(new Log());

I used RegisterInstance for Log. In most applications you will only need one instance of a Logger. In this case we create the instance of Log and associate it with ILog. Now anytime unity is asked to resolve ILog it will create a concrete implementation of Log and return it as ILog.

unityContainer.RegisterType<IA, A>(
    new InjectionConstructor(
        container.Resolve<ILog>()
    )
);

I used RegisterType for A. Since A will be created more than once we want to give Unity instructions about what to inject into it and not actually create an instance now. InjectionConstructor is what keeps track of what dependencies should be injected into the constructor of A.

Note that we can now inject A in another class by resolving IA:

new InjectionConstructor(
    container.Resolve<IA>()
)

We've has only scratched the surface of Microsoft Unity IoC capabilities but I hope I've provided you a good start to developing more manageable code bases.

No comments:

Post a Comment