IoC容器 - 单例还是传递实例?

Sch*_*999 8 c# design-patterns dependency-injection ioc-container

可能重复:
创建单例来访问Unity容器或通过应用程序传递它是否更好?

我正在将IoC容器引入系统.自然的问题是,它应该是单例还是传递给类使用的实例?我倾向于将它作为单例实例,因为:

  1. 不需要像构造函数,附加属性那样混淆类定义.
  2. 更清晰 - 每个应用程序一个实例,一个初始化路由.
  3. 能够在必要时使用覆盖进行默认映射(例如单元测试).

以下是它的外观:

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

有什么我想念的,而实际上我应该有这样的东西:

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

当然,对于第二种方法,我可能总是通过传递单例容器实例来回退到第一种方法.

编辑:更新的代码示例

Jef*_*nal 32

两者都没有:这两种方法都隐藏了你的依赖关系并使你的类难以使用.相反,Foo应该IBar在其构造函数中要求:

class Foo {
    private bar;
    public Foo(IBar bar) { this.bar = bar; }
    private void DoBarStuff() {
        this.bar.DoStuff();
    }
}
Run Code Online (Sandbox Code Playgroud)

关于容器应该知道的唯一事情是应用程序入口点.

请参阅依赖注入神话:参考传递服务定位器是一种反模式,可进行更深入的讨论.

  • @Sparkie - 在这些情况下,你通常需要一个`IBarFactory`并推迟创建,直到你有足够的信息来创建一个`Bar`实例. (2认同)