I may have gone overboard with implementing dependency injection using Ninject on a project at work. I ended up with multiple calls to the kernel when creating each object. Worse yet I’ve used the [Inject] attribute to implement the binding, building up hundreds of dependencies on the Ninject library. At the time this seemed to make implementing things easier, especially as this was the first time I had used a dependency injection library, and I didn’t see a problem with a dependency on what seems like a core component.
I separated out 30 or so repositories, set up a heap of fakes, hooked up a handful of tests, and jumped into implementing the latest feature. Everything went well in development, I deployed, and all was shiny. Then the trouble started.
First the users started complaining about speed. Some operations were taking 10-20 times as long to run as before. That was because of calls to Ninject happening whenever many objects were being created, and inside of loops. Then some older Winforms components turned out to crash in the designer. That was due to the Ninject kernel not being set up when the component is executed by the designer – the new dependency on Ninject was failing. Then I read an article by Bob Martin and several of his tweets on the subject where he talks about the dependency framework itself becoming a dependency. Got that right.
I decided to replace the direct dependency injection via Ninject with a factory. This way the factory is the only place with the dependency on Ninject, and has the option of returning a mock if there is Ninject isn’t configured (to deal with the designer issues). It also lets me inject the dependency only once and reuse the result.
I set up a simple test to see what effect moving the dependency injection out of the loop would have on the speed. The first consumer of the test is has the DI on construction:
class InjectionTester
{
[Inject] public IAdditionProvider Adder { get; set; }
public int DoAdd(int a, int b) { return Adder.Add(a, b); }
}
...
// test using injection in the loop
for (int i = 0; i < 1000; i++)
{
for (int j = 0; j < 1000; j++)
{
var tester = NinjectContainer.Kernel.Get<InjectionTester>();
tester.DoAdd(i, j);
}
}
The second consumer of the test uses a factory to get the dependency:
class AdditionProviderFactory
{
public static AdditionProviderFactory Instance = new AdditionProviderFactory();
IAdditionProvider additionProvider;
object additionProviderLock = new object();
public IAdditionProvider AdditionProvider
{
get
{
lock (additionProviderLock)
{
additionProvider = additionProvider ?? NinjectContainer.Kernel.Get<IAdditionProvider>();
}
return additionProvider;
}
}
}
class FactoryTester
{
IAdditionProvider Adder = AdditionProviderFactory.Instance.AdditionProvider;
public int DoAdd(int a, int b) { return Adder.Add(a, b); }
}
...
// test using the factory
for (int i = 0; i < 1000; i++)
{
for (int j = 0; j < 1000; j++)
{
var tester = new FactoryTester();
tester.DoAdd(i, j);
}
}
The results are pretty impressive (looping a million times):

Thinking about it now it’s pretty obvious that DI is going to be a bit expensive, but seriously, using a factory is over 200 times faster. That should keep em quiet.