8

Possible Duplicate:
Is it better to create a singleton to access unity container or pass it through the application?

I am introducing IoC container into the system. The natural question is, should it be a singleton or an instance passed to a class to use? I lean towards having it as a singleton instance because:

  1. No need to clutter class definition like constructors, additional properties.
  2. Clearer - one instance per application, one initialization routing.
  3. Ability to have default mapping with overrides if necessary (like for unit testing).

Here is how it looks:

class Main
{
  public static void main(params string[] args)
  {
     IoCContaner.Intance.Add<IBar>();
     IoCContaner.Intance.Add<IBaz>();
     IoCContaner.Intance.Add<IQux>();

     var foo = new Foo();
     Foo.DoBarStuff();
  }
}

class Bar : IBar 
{ 
  public Bar(IBaz, IQuz) {} 
  public void DoBazStuff() { _baz.DoStuff(); }
}

class Foo
{
  public void DoBarStuff()
  {
     var bar = IoCContaner.Intance.Resolve<IBar>();
     bar.DoBazStuff();
  }
}

Is there anything I am missing and instead I should actually have something like:

class Foo
{
  IoCContainer _c;
  public Foo(IoCContainer c) { _c = c; }
  ...
  private void DoBarStuff()
  {
     var bar = _c.Resolve<IBar>();
     bar.DoBazStuff();
  }
}

Of course with the second approach I may always to fall back to the first one by passing around a singleton container instance.

EDITED: updated code examples

Community
  • 1
  • 1
Schultz9999
  • 8,717
  • 8
  • 48
  • 87
  • 1
    Duplicate: http://stackoverflow.com/questions/2386487/is-it-better-to-create-a-singleton-to-access-unity-container-or-pass-it-through-t – Mark Seemann Jan 27 '11 at 19:25
  • Voted myself to close as dup. Besides the only answer is diverged the attention from IoC usage to DI, which is not the thing I am asking about. Please vote to close. – Schultz9999 Jan 28 '11 at 02:16

1 Answers1

32

Neither: both of those approaches hide your dependencies and make your classes hard to use. Instead, Foo should require an IBar in its constructor:

class Foo {
    private bar;
    public Foo(IBar bar) { this.bar = bar; }
    private void DoBarStuff() {
        this.bar.DoStuff();
    }
}

The only things that should know about your container are your application entry points.

See Dependency Injection Myth: Reference Passing and Service Locator is an Anti-Pattern for additional in-depth discussion.

Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
  • Boom. The only correct answer. – jason Jan 27 '11 at 19:07
  • 1
    What if some particular condition within Foo is required to create your Bar, such that you can't instantiate your Bar before creating Foo, but instead need to pass a Type to it. – Mark H Jan 27 '11 at 19:17
  • 2
    @Sparkie - in those cases, you usually require an `IBarFactory` and defer creation until you have enough information to create a `Bar` instance. – Jeff Sternal Jan 27 '11 at 19:18
  • @Jeff: I don't want to deal with passing things around. That's why I want IoC container. It will wire classes up for me, no matter how many dependencies exist. That's its purpose and I don't think you are getting the sense of it. – Schultz9999 Jan 28 '11 at 01:21
  • @to all: I am sorry but that's not acceptable answer for me because having IFoo, IBar, IBaz, and 10 more interfaces with corresponding implementation that depend on each other, setting all this up is tedious and error prone. That's what IoC container is for. Jeff is welcome to do it manually but I'd rather rely on IoC container rather than on developers. – Schultz9999 Jan 28 '11 at 01:25
  • BTW, who are those guys who you give references to? – Schultz9999 Jan 28 '11 at 01:50
  • @Jeff: "@Sparkie - in those cases, you usually require an IBarFactory" that's exactly what IoC container is, which I dare to say you don't get the understanding of... People, please read the question and stop bumping up this answer. – Schultz9999 Jan 28 '11 at 02:00
  • @Schultz - sorry I wasn't clear. I wasn't saying you shouldn't use a container, just that you should only use it at the top of your object graph. – Jeff Sternal Jan 28 '11 at 02:58
  • I'm going to answer. "Neither" also, static class with static members will suffice for a Wrapper around your IoC container. – Phill Jan 28 '11 at 03:36
  • @Phill: that's what IoCContaner.Intance is for, don't you think? – Schultz9999 Jan 28 '11 at 05:18
  • @Schultz9999 /facepalm forget it. http://www.manning.com/seemann/ – Phill Jan 28 '11 at 05:54