R – Why not pass your IoC container around

dependency-injectioninversion-of-control

On this AutoFac "Best Practices" page (http://code.google.com/p/autofac/wiki/BestPractices), they say:

Don't Pass the Container Around
Giving components access to the container, or storing it in a public static property, or making functions like Resolve() available on a global 'IoC' class defeats the purpose of using dependency injection. Such designs have more in common with the Service Locator pattern.
If components have a dependency on the container, look at how they're using the container to retrieve services, and add those services to the component's (dependency injected) constructor arguments instead.

So what would be a better way to have one component "dynamically" instantiate another? Their second paragraph doesn't cover the case where the component that "may" need to be created will depend on the state of the system. Or when component A needs to create X number of component B.

Best Answer

To abstract away the instantiation of another component, you can use the Factory pattern:

public interface IComponentBFactory
{
    IComponentB CreateComponentB();
}

public class ComponentA : IComponentA
{
    private IComponentBFactory _componentBFactory;

    public ComponentA(IComponentBFactory componentBFactory)
    {
        _componentBFactory = componentBFactory;
    }

    public void Foo()
    {
        var componentB = _componentBFactory.CreateComponentB();

        ...
    }
}

Then the implementation can be registered with the IoC container.

A container is one way of assembling an object graph, but it certainly isn't the only way. It is an implementation detail. Keeping the objects free of this knowledge decouples them from infrastructure concerns. It also keeps them from having to know which version of a dependency to resolve.

Related Topic