1

I believe I understand enough about dependency injection to get started with it, but I'm having trouble understanding IOC containers vs service location, and how to construct my objects utilizing the container.

Given:

public interface IFooService
{
    void DoSomethingFooey();
}
public class FooService : IFooService
{
    readonly IBarService _barService;

    public FooService(IBarService barService)
    {
        this._barService = barService;
    }

    public void DoSomethingFooey()
    {
        // some stuff
        _barService.DoSomethingBarey();
    }
}


public interface IBarService
{
    void DoSomethingBarey();
}
public class BarService : IBarService
{
    readonly IBazService _bazService;

    public BarService(IBazService bazService)
    {
        this._bazService = bazService;
    }

    public void DoSomethingBarey()
    {
        // Some more stuff before doing ->
        _bazService.DoSomethingBazey();
    }
}


public interface IBazService
{
    void DoSomethingBazey();
}
public class BazService : IBazService
{
    public void DoSomethingBazey()
    {
        Console.WriteLine("Blah blah");
    }
}

Without an IOC container I would have to provide all of my dependencies at construction like so:

    public void DoStuff()
    {
        // Without a container, I would have to do something yucky like:
        FooService fs = new FooService(
            new BarService(
                new BazService()
            )
        );

        // or
        BazService bazService = new BazService();
        BarService barService = new BarService(bazService);
        FooService fooService = new FooService(barService);
    }

I am gaining seemingly a lot by constructing my classes in this DI manner, because I can now independently test my classes, when before using DI I really couldn't.

But with what I'm reading about the "proper way" of doing DI, I would use an IOC container like Unity or StructureMap... but I haven't found exactly what I need to understand how to get started.

I'm going to assume my container would look something like this:

var container = new Container(_ =>
{
    _.For<IFooService>().Use<FooService>();
    _.For<IBarService>().Use<BarService>();
    _.For<IBazService>().Use<BazService>();
});

That was taken from the example at: http://structuremap.github.io/quickstart/

Based on the above example, I'm unsure of what the signature of the method containing var container... looks like, or how it is called and kept within scope. And perhaps more importantly how to actually construct the object utilizing the container.

What does my DoStuff() look like now if I wanted to create an instance of FooService (and in turn BarService and BazSerivce)?

Previously it was:

public void DoStuff()
{
    // Without a container, I would have to do something yucky like:
    FooService fs = new FooService(
        new BarService(
            new BazService()
        )
    );

    // or...
}

But what does it look like now utilizing my container? And how does my method know where to look for my container?

Hopefully I'm somewhat on the right track, but please let me know if I'm not, and what I'm missing.

Kritner
  • 13,557
  • 10
  • 46
  • 72
  • 2
    What you are missing is the concept of the [Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot/). – Steven Dec 17 '15 at 20:37
  • 2
    Don't be fooled by people who say that using IOC containers is "the proper way to do DI". You can either use a container, or practice [Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di/). Both have their value and ups and downs. It's always good to question [when to use a container](https://simpleinjector.org/blog/2015/12/when-should-you-use-a-container/). – Steven Dec 17 '15 at 20:39
  • @Steven Would what I'm currently doing by newing up my object be considered "Pure DI"? Or does that also require a composition root? Those articles, while informative, are still pretty abstract at least to me, I wanted to get something a little more concrete. – Kritner Dec 18 '15 at 12:40
  • 1
    With Pure DI, you build your object graphs in the composition root. – Steven Dec 18 '15 at 12:50

2 Answers2

2

Your DoStuff method revised to use the container would look something like this:

public void DoStuff()
{
    IFooService fooService = container.GetInstance<IFooService>();

    // do something with fooService
}

I'm basing this off of the StructureMap link that you referenced. Other IoC containers name their equivalent "GetInstance" method differently.

You wouldn't normally create your container within the same method where you're trying to obtain an instance of IFooService though. Typically, you'd configure your container elsewhere in some initialization method and keep the container somewhere that you can access easily, such as in a static property. So, your DoStuff method might look more like this:

public void DoStuff()
{
    IFooService fooService = MyIoCContainer.Current.Getinstance<IFooService>();

    // do something with fooService
}

where MyIoCContainer is just a class that you've defined, and its Current property is the StructureMap container that you configured during initialization.

However, you're not always required to write code like this in order to obtain your services. Some frameworks provide hooks to make use of your IoC container so that you continue to use dependency injection all the way through your classes, and the framework takes care of instantiating your classes using your IoC container.

Just one example, the ASP.NET MVC framework provides an IDependencyResolver interface and DependencyResolver class that you can use to allow that framework to use your IoC container when instantiating your controller classes in your web application. That way, you can continue to use dependency injection all the way up into your controllers and therefore don't need to explicitly reference your IoC container within your controllers at all. See this section on "Including a Custom Dependency Resolver" for how that is accomplished.

So, ideally your DoStuff method and its containing class would look something like this, which is just a further continuation of dependency injection. The question then is how this MyStuffDoer class gets instantiated: either by a framework that understands how to use your IoC container to create it, or by you writing some explicit code somewhere to instantiate it from the IoC container.

class MyStuffDoer
{
    IFooService fooService;

    public MyStuffDoer(IFooService fooService)
    {
        this.fooService = fooService;
    }

    public void DoStuff()
    {
        // do something with fooService
    }
}
Dr. Wily's Apprentice
  • 10,212
  • 1
  • 25
  • 27
  • 1
    Thanks, but how is your provided DoStuff() different than the service locator pattern? Doesn't doing the resolving in this manner couple my class (and every other class that would utilize the container) to my IOC container? – Kritner Dec 18 '15 at 12:42
  • 1
    @Kritner The simple example I provided of using the IoC container's `GetInstance` method isn't really different than the service locator pattern. I updated my answer to talk about the fact that some frameworks may provide ways to utilize your IoC container so that you don't have to write that code. – Dr. Wily's Apprentice Dec 18 '15 at 16:11
-2

I usually do this to keep DI and avoid drawbacks of IOC containers:

public interface IFooService
{
    void DoSomethingFooey();
}
public class FooService : IFooService
{
    readonly IBarService _barService;

    public FooService() : this(new BarService()) {}

    public FooService(IBarService barService)
    {
        this._barService = barService;
    }

    public void DoSomethingFooey()
    {
        // some stuff
        _barService.DoSomethingBarey();
    }
}


public interface IBarService
{
    void DoSomethingBarey();
}
public class BarService : IBarService
{
    readonly IBazService _bazService;

    public BarService() : this(new BazService()) {}

    public BarService(IBazService bazService)
    {
        this._bazService = bazService;
    }

    public void DoSomethingBarey()
    {
        // Some more stuff before doing ->
        _bazService.DoSomethingBazey();
    }
}


public interface IBazService
{
    void DoSomethingBazey();
}
public class BazService : IBazService
{
    public void DoSomethingBazey()
    {
        Console.WriteLine("Blah blah");
    }
}
Riad Baghbanli
  • 3,105
  • 1
  • 12
  • 20
  • Having default constructors that inject into overloaded constructors is bad practice, because this causes strong-coupling between components (a Dependency Inversion Principle violation) and makes components less reusable, and makes it very hard to apply cross-cutting concerns (using decorators or interception) without having to make sweeping changes throughout the code base. – Steven Dec 17 '15 at 20:36
  • Additionally I would never be able to get 100% coverage (not that 100% coverage is required) due to the parameterless constructor that news up the class with the concrete implementation of the interface. I can't test the parameterless constructor as there could be some impact to actual application data. – Kritner Dec 18 '15 at 12:55