7

(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".

Alex
  • 3,429
  • 4
  • 36
  • 66

2 Answers2

14

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
  • 138,234
  • 66
  • 282
  • 345
  • 1
    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 Mar 29 '10 at 18:10
  • 2
    @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 Mar 29 '10 at 18:27
  • @chris_l: So then "Providers" can keep the Injector around, right? Otherwise we've just moved the problem elsewhere. – Alex Mar 29 '10 at 18:53
  • 2
    @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 Mar 29 '10 at 19:06
  • 2
    Some containers (Autofac, Funq, latest Unity, others) let you use Func as a provider, so to create instances of Button, take a dependency on Func – Nicholas Blumhardt Mar 29 '10 at 20:26
  • 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 Kozmic Mar 29 '10 at 21:35
2

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: Accessing the DI container

Community
  • 1
  • 1
Chris Lercher
  • 37,264
  • 20
  • 99
  • 131