4

Let's say we have class:

public class WithDependencies
{
  public WithDependencies(IAmDependencyOne first, IAmDependencyTwo second)
  // ...
}

Now the question. How do you create objects of WithDependencies class in an application? I know there are many ways.

new WithDependencies(new DependencyOne(), new DependencyTwo());
new WithDependencies(IoC.Resolve(IDependencyOne), IoC.Resolve(IDependencyTwo());
// register IDependencyOne, IDependencyTwo implementations at app start
IoC.Resolve(WithDependencies);
// register IDependencyOne, IDependencyTwo implementations at app start
// isolate ourselves from concrete IoC Container
MyCustomWithDependenciesFactory.Create();

and so on...

What do you think is the way to do it?

Edit:

Because I don't get answers or I don't understand them I'll try to ask again. Let's say that on some event (button, timer, whatever) I need new object WithDependencies(). How do I create it? Assume IoC container is already configured.

Piotr Perak
  • 10,718
  • 9
  • 49
  • 86
  • I think any answer to this will start out with "It depends"... I've seen arguments for the first approach because it at least keeps your dependencies organized in a sort of hierarchy, instead of requiring some big global service provider. – Nathan Monteleone Nov 17 '11 at 19:05

3 Answers3

3

It depends on the context, so it's impossible to provide a single answer. Conceptually you'd be doing something like this from the Composition Root:

var wd = new WithDependencies(new DependencyOne(), new DependencyTwo());

However, even in the absence of a DI Container, the above code isn't always unambiguously the correct answer. In some cases, you might want to share the same dependency among several consumers, like this:

var dep1 = new DependencyOne();
var wd = new WithDependencies(dep1, new DependencyTwo());
var another = AnotherWithDependencies(dep1, new DependencyThree());

In other cases, you might not want to share dependencies, in which case the first option is more correct.

This is just a small glimpse of an entire dimension of DI concerned with Lifetime Management. Many DI Containers can take care of that for you, which is one excellent argument to prefer a DI Container over Poor Man's DI.

Once you start using a DI Container, you should follow the Register Resolve Release pattern when resolving types, letting Auto-wiring take care of the actual composition:

var wd = container.Resolve<WithDependencies>();

The above example assumes that the container is already correctly configured.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • I really hoped you would answer this question. Your book has been on my amazon wishlist long before it was published. Will read it soon. I understand Lifetime Managment. I guess my question was is calling container.Resolve on for example button click ok. Or should I not use container object directly. – Piotr Perak Nov 17 '11 at 22:50
  • Using it directly on a button click is the Service Locator anti-pattern, so no: you shouldn't do that: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx – Mark Seemann Nov 18 '11 at 07:56
  • I don't understand. I read your article in the past. I understood that passing IServiceLocator to WithDependencies object instead of IAmDependencyOne, IAmDependencyTwo is a ServiceLocator anti-pattern. I thought about doing it this on btn click: IoC.Resolve(); Not passing IoC to WithDependencies ctor. – Piotr Perak Nov 18 '11 at 17:41
2

If you need to create a dependency which has its own dependencies, you can either A) do it yourself, or B) ask something else to do it for you. Option A negates the benefits of dependency injection (decoupling, etc.), so I would say option B is a better starting point. Now, we have chosen to use the factory pattern, no matter whether it takes the form of a service locator (i.e. IoC.Resolve), a static factory, or an instance factory. The point is that we have delegated that responsibility to an external authority.

There are a number of trade-offs required for static accessors. (I went over them in another answer, so I won't repeat them here.) In order to avoid introducing a dependency on the infrastructure or the container, a solid option is to accept a factory for creating 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 implementation of the factory:

public class WithDependenciesFactory : IWithDependenciesFactory
{
    private readonly IContainer _container;

    public WithDependenciesFactory(IContainer container)
    {
        _container = container
    }

    public WithDependencies Create()
    {
        return _container.Resolve<WithDependencies>();
    }
}

Now NeedsWithDependencies is completely isolated from any knowledge of how WithDependencies gets created; it also exposes all its dependencies in its constructor, instead of hiding dependencies on static accessors, making it easy to reuse and test.

Defining all those factories can get a little cumbersome, though. I like Autofac's factory relationship type, which will detect parameters of the form Func<TDependency> and automatically inject a function which serves the same purpose as the hand-coded factory 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...
    }
}
Community
  • 1
  • 1
Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • I'm not sure I understand first example. I understand that you propose creating factory of WithDependencies. But when we have it why pass it to NeedsWithDependencies ctor instead of handing it already created (using factory) WithDependencies object? That way NeedsWithDependencies doesn't have know about factory and is easier to test (no need to setup mocks in tests). BTW There is a typo in name of WithDependenciesFactory ctor. – Piotr Perak Nov 17 '11 at 22:39
  • @Peri: I interpreted your question to be about creating instances of `WithDependencies` on-demand, i.e. waiting to instantiate them until you actually need them. That is how I think about factories in a DI context. I realize now, though, that your question is more about using an IoC container in general. @Mark Seemann's answer about using a Composition Root addresses that well. – Bryan Watts Nov 18 '11 at 00:22
0

Sometimes I try to get rid of factories or at least not depend directly on them, so Dependency Injection (without factories) is useful of course.

Therefore I use Google Juice, cause its a small little framework using Java Annotations and you can quickly change your injections / dependencies. Just take a look at it:

http://code.google.com/p/google-guice/

philomatic
  • 350
  • 1
  • 3
  • 10