views:

163

answers:

5

Is the example below dependency injection with regard to the Worker class? From my reading about the topic over the last few hours becaue the Worker class isn't obtaining the ITool instance from a property setter or constructor it isn't an example of DI?

public MainClass {

    static void Main(string[] args) {
        ITool someTool = new Tool();
        MyContainer.Register<ITool>(someTool);
    }
}

public class MyContainer {

    private WindsorContainer container;

    public MyContainer() {
        container = new WindsorContainer();
    }

    public static T Resolve<T>() {
        return container.Resolve<T>();
    }

    public static void Register<T>(object instance) {
        container.Kernel.AddComponentInstance(typeof(T).ToString(), typeof(T), instance);
    }
}

public class Worker {

    public DoSomeWork() {
        ITool tool = MyContainer.Resolve<ITool>();
        tool.DoTheWork();
    } 
}
+4  A: 

For me it's an example of Inversion of Control, and the Dependency Inversion Princial, as the Worker class is requesting the ITool from the container, rather than instantiating it itself, but it's not really an example of Dependency Injection as the dependency isn't "injected" from externally, it's "requested" from internally.

The terms can be quite confusing, and are often used interchangeably (incorrectly), however as long as your code is decoupled so you're not reliant on concrete implementations or "new-ing" things up in your "modules" then you are gaining the core advantages.

Personally it's very rare that I don't do constructor injection, even if I'm not using an overarching container - I find it the easiest method for unit tests etc.

Steven Robbins
+4  A: 

Well, I guess it's not strictly 'injecting' the dependency. Worker still has a hard-coded dependency on MyContainer - I guess 'true' dependency injection would involve passing an ITool to Worker, instead of Worker looking up ITool.

harto
Cool avatar :-)
Steven Robbins
+4  A: 

What you have here is "Service Location" rather than "Dependency Injection", although both are examples of "Inversion of Control".

You'll want to read "Inversion of Control Containers and the Dependency Injection pattern", and pay close attention to this section.

Don't worry if you feel overwhelmed, it's a lot to take in all at once. For a slightly more structured introduction to a real world dependency injection tool, I highly recommend the Ninject User Guide.

anthony
hmm not really. service locator is just a fancy factory, NOT a kind if IoC.
Andreas Petersson
+1 A further problem with the approach outlined above is that the Resolve method is static.
Mark Seemann
Andreas: Cool story bro.
anthony
A: 

In addition to everything in Steven Robbins's answer, this is also an example of the Service Locator pattern, since the MyContainer class is acting like a Registy inside the Worker class

Jon Schoning
+2  A: 

IoC with containers is not as useful as dependency injection.

If you're not passing it in, you're not getting the advantages very much of anything. You're still heavily relying on a singleton-style global: your container object. Once you inject (pass) in the container object, you aren't gaining any benefit from the container! And, you also end up passing in an object that can resolve all kinds of global objects that you don't need! So why do it? It adds unneeded complexity. Containers and registries are good examples of astronaut ways of thinking.

Pass in exactly what you need, and only what you need. If you need something that implements ITool, pass it in. Don't forget to hint the passed in object as the ITool interface. That's all you need.

RibaldEddie
That's pretty much what I was thinking as well. The sample code was from someone else's code and I was trying to understand why they would skip DI after the effort/overhead of a Service Location approach.
sipwiz