views:

171

answers:

2

(This question does not rely on a specific IoC framework, so the interfaces and types in my samples are meta-types. Just replace them with the appropriate types for your favorite IoC framework in your head.)

In my main methods, I typically set up my container doing something like this:

static void Main()
{
    IInjector in = new Injector();
    in.Register<ISomeType>().For<SomeType>();
    in.Register<IOtherType().For<OtherType>();
    ...

    // Run actual application
    App app = in.Resolve<App>();
    app.Run();
}

My question is, how do you get the Injector sent around? I've normally just registered the injector with itself and had it injected into types that themselves are going to do injection, but I'm not sure if this is the proper "pattern".

+10  A: 

You shouldn't pass the container around.

Instead, your entry-point/main method asks the container for the objects it needs to get started - such as your App object/bean. The container then returns the full object graph connected to App, which allows you to run app.Run(), with all the dependencies satisfied.

It's a bit of an anti-pattern for the objects to be aware of the container, or for each object to be asking the container for it's dependencies - if you do this then you have not inverted control and what you have is not dependency injection - you still have objects asking for what they need, rather than being given what they need.

matt b
Okay, how about this. The App is a WinForm and has a button that creates and shows a form. Each time this button is pushed, a new instance of this form should be created and shown. This form has dependencies, so it needs to be resolved by the App Form for each instantiation. Now what?
Alex
@Alex: In this case you can use "Providers" (specialized Factories) I mentioned in my other post. The difference between injecting a Provider, and injecting the entire injector is, that this strongly limits the indirect, "secret" dependencies. IOW, it doesn't degrade the Injector to a Service Locator.
Chris Lercher
@chris_l: So then "Providers" can keep the Injector around, right? Otherwise we've just moved the problem elsewhere.
Alex
@Alex: Providers are free to construct a certain kind of object that belongs to the module, including all of its dependencies (but they should not perform program execution logic). They are part of the construction code, so they can keep the injector around (or just the parts of it they need). The most important thing about dependency injection is definitely to separate construction code from execution code. Providers offer a means to request a bit of construction where it's needed in the execution part (because it shouldn't do it by itself).
Chris Lercher
Some containers (Autofac, Funq, latest Unity, others) let you use Func<T> as a provider, so to create instances of Button, take a dependency on Func<Button> and the container does the rest. See http://nblumhardt.com/2010/01/the-relationship-zoo/ for some more details.
Nicholas Blumhardt
Others (Windsor, trunk version of StructureMap) let you define an abstract factory interface, and have the container provide the implementation for it. See http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx for some more details ;)
Krzysztof Koźmic
+2  A: 

It's best to avoid injecting the injector. Just create the types you need, and then start executing. I've written a somewhat longer post on this topic: http://stackoverflow.com/questions/2504798/dependency-injection-in-constructors/2505059#2505059

Chris Lercher