If you need to create a dependency that has its own dependencies, you can either A) do it yourself, or B) ask for something else to do for you. Option A denies the benefits of dependency injection (decoupling, etc.), so I would say that option B is the best starting point. Now we decided to use the factory template, regardless of whether it takes the form of a service locator (i.e., IoC.Resolve ), a static factory, or an instance of a factory. The fact is that we have delegated this responsibility to an external body.
There are a number of tradeoffs needed for static accessories. ( I looked at them in another answer , so I wonβt repeat them here.) To avoid introducing a dependency on the infrastructure or container, is to take a factory to create WithDependencies when we need an instance somewhere else:
public class NeedsWithDependencies { private readonly IWithDependenciesFactory _withDependenciesFactory; public NeedsWithDependencies(IWithDependenciesFactory withDependenciesFactory) { _withDependenciesFactory = withDependenciesFactory; } public void Foo() { var withDependencies = _withDependenciesFactory.Create(); ...Use the instance... } }
Next, we can create a container-specific factory implementation:
public class WithDependenciesFactory : IWithDependenciesFactory { private readonly IContainer _container; public WithDependenciesFactory(IContainer container) { _container = container } public WithDependencies Create() { return _container.Resolve<WithDependencies>(); } }
Now NeedsWithDependencies completely isolated from any knowledge of how WithDependencies is created; it also exposes all its dependencies in its constructor instead of hiding dependencies on static accessories, which simplifies reuse and testing.
Defining all of these plants can be a little cumbersome. I like the Autofac factory relationship type , which will determine the parameters of the Func<TDependency> form and automatically introduce a function that performs the same task as the manual factory code above:
public class NeedsWithDependencies { private readonly Func<WithDependencies> _withDependenciesFactory; public NeedsWithDependencies(Func<WithDependencies> withDependenciesFactory) { _withDependenciesFactory = withDependenciesFactory; } public void Foo() { var withDependencies = _withDependenciesFactory(); ...Use the instance... } }
It also works great with runtime parameters:
public class NeedsWithDependencies { private readonly Func<int, WithDependencies> _withDependenciesFactory; public NeedsWithDependencies(Func<int, WithDependencies> withDependenciesFactory) { _withDependenciesFactory = withDependenciesFactory; } public void Foo(int x) { var withDependencies = _withDependenciesFactory(x); ...Use the instance... } }