Learning to keep things about your application hidden is important. Your code should be exposed to as few things as possible. Using tools like Ninject, Structuremap, etc. is great, but you should try to keep them at arm’s length.
If you want to keep your Inversion of Control (IoC) container hidden you can put a nice wrapper around it. In an application I am currently working with I started by using an IoC container that was very simple. Just enough so that I didn’t have to use the poor man’s dependency injection.
I start with these ten minute home-grown IoC containers for a few reasons. One reason is that they’re quick and easy. Another is that I wanted the developer I was working with to understand how IoC containers work, so having him deal with the inner-workings on an IoC container will give him that knowledge. Also I really don’t always make a decision on which IoC container to use until I see what features will be needed for an application. If one of them will give me an issue I don’t want to be using it. To say it in a nice way, I don’t like trying to force the square peg into the round hole.
Your own container
To start you’ll really want to have a class you can use to give you access to the container you’re using. This is the face of IoC in your application. It isn’t necessarily an IoC container since we’re really just going to have it pass the calls through.
We need to create a simple class. We will call it IoC for this example. I like that name since it is extremely short, so when we use it we aren’t making our lines excessively long.
public class IoC
{
}
Resolving Dependencies
The main task we use an IoC container for is to resolve our dependencies. We want to get objects of certain types from it. So we need some kind of Resolve or Get method on the class. In this case I am going to use a static method. Calm down! Static methods can be used sparingly. We just have to be careful with them and keep them very simple.
public class IoC
{
public static T Resolve<T>()
{
throw new NotImplementedException();
}
}
So I need to have something to resolve these dependencies for me. We want to depend on Interfaces and abstractions only, so I will create an interface for a dependency resolver. Then this static method can call through to that interface. This IoC class is really just here for convenience so I don’t have to pass around an instance of my interface everywhere.
public interface IResolver
{
T Resolve<T>();
}
So now I can add this interface into my IoC class. I want to have a static instance of this interface and I want to have a method that will allow me to set the IResolver.
public class IoC
{
private static IResolver _resolver;
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
public static void Initialize(IResolver resolver)
{
_resolver = resolver;
}
}
Now we’ve got our IoC class finished up. Sure it doesn’t do anything yet, but we can test with this thing by initializing it with a mock, fake, stub, cake, etc.
Using Your Favorite IoC Container
Now that we have this nice interface in place we are set to wire things up. We can use anything we want to actually do the registering and resolving of our dependencies. If you’re ambitious go write your own. If not go grab something else. I’ll use Ninject in this example.
So I will create a concrete implementation of the IResolver interface and I will call it the NinjectResolver. This class will act as my go between for working with Ninject. I make this class inherit from the StandardModule from Ninject and implement my IResolver interface.
public class NinjectResolver : StandardModule, IResolver
{
private readonly StandardKernel _kernel;
public NinjectResolver()
{
_kernel = new StandardKernel(this);
}
public T Resolve<T>()
{
return _kernel.Get<T>();
}
public override void Load()
{
Bind<IAmAnInterface>().To<ConcreteCLass>();
}
}
I am using the StandardKernel from Ninject, and am overriding the Load method from the StandardModule class. In the Load method I am registering the dependencies with the IoC container. Then when I want to get instances of the dependencies from the container I will be calling the IResolver.Resolve<>() method and it will just pass through to the StandardKernel.Get<>() method. Pretty simple actually.
Putting Everything Together
Now when my application initializes I just create an instance of the NinjectResolver and call its Load method. After that I pass this in to the IoC class using the Initialize method. Now we go celebrate because we can use this simple code to get an instance of IAmAnInterface in the form of ConcreteClass.
IAmAnInterface impl = IoC.Resolve<IAmAnInterface>()
I hope you’ve enjoyed today’s IoC fun. Please pass forward yesterday’s homework. Tonight your assignment is to figure out how to register your own dependencies without using Ninject. I recommend taking a look at the Dictionary class or something similar.
Comments