C# Dependency Injection – Per-Method-Call Instantiation Without IoC Container

cdependency-injectioninversion-of-controlioc-containersnet

I read with interest this article which states:

A DI Container should only be referenced from the Composition Root. All other modules should have no reference to the container.

This means that all the application code relies solely on Constructor Injection (or other injection patterns), but is never composed. Only at the entry point of the application is the entire object graph finally composed.

I take it to mean all instances should be injected, never instantiated by anything other than the IoC container.

Under this pattern, this is not allowed:

class MyClass {
    void SomeMethod() {
        var w = new Worker();
        w.DoSomething();
    }
}

Instead it should look more like this:

class MyClass {
    protected readonly IWorker _worker;
    public MyClass(IWorker worker) {
        _worker = worker;
    }
    void SomeMethod() {
        _worker.DoSomething();
    }
}

This works fine if I only need one instance of Worker per instance of MyClass. But what if Worker is stateful (or worse, Disposable) and I need a new instance each time SomeMethod is called?

I could do something like this:

class MyClass {
    protected readonly IUnityContainer _container;
    public MyClass(IUnityContainer container) {
        _container = container;
    }
    void SomeMethod() {
        using (var w = _container.Resolve<IWorker>()) {
            w.DoSomething();
        }
    }
}

But that technique is frowned upon by this article, and also it violates the principle that the container should only be referenced from the composition root.

I could inject a factory:

class MyClass {
    protected readonly IWorkerFactory _factory;
    public MyClass(IWorkerFactor factory) {
        _factory = factory;
    }
    void SomeMethod() {
        using (var w = _factory.Create<IWorker>()) {
            w.DoSomething();
        }
    }
}

…which seems to address the issue. But then when I go to write the factory, I have to reference the container again:

class WorkerFactory : IWorkerFactory
{
    protected readonly IUnityContainer _container;

    public WorkerFactory(IUnityContainer container) {
        _container = container;
    }

    public T Create<T>() where T : IWorker {
        return _container.Resolve<T>();
    }
}

…so really, it seems, I have moved the problem, not solved it.

If it is true that "A DI Container should only be referenced from the Composition Root," I don't see how that is possible for per-method-call instantiation.

How do I support per-method-call instantiation without referencing the container from outside the composition root?

Best Answer

Most IoC containers will provide a method for automatically implementing a factory. See for example:

The IoC container will create an instance of a factory that will, if configured properly, return a new object with every call to a method.

This works, because the container will generate code that for the factory that references the container and uses it to satisfy the dependencies of the objects you're creating. If your IoC container is not so mature and doesn't have that facility then you'll need to write your own factory, and that factory will likely have to reference the IoC container directly. I would say this case is an exception to the rule, and as long as your references to the container are kept sequestered in your factory implementations and don't leak out anywhere, then you will still be following the spirit of the rule.

Related Topic