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

时间:2011-01-27 18:57:32

标签: c# dependency-injection design-patterns ioc-container

  

可能重复:
  Is it better to create a singleton to access unity container or pass it through the application?

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

  1. 不需要像构造函数,附加属性那样混淆类定义。
  2. 更清晰 - 每个应用程序一个实例,一个初始化路由。
  3. 如有必要,可以使用覆盖进行默认映射(例如单元测试)。
  4. 以下是它的外观:

    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();
      }
    }
    

    我有什么遗漏,而实际上我应该有:

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

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

    已编辑:更新的代码示例

1 个答案:

答案 0 :(得分:32)

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

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

应该了解容器的唯一事项是应用程序入口点。

有关其他深入讨论,请参阅Dependency Injection Myth: Reference PassingService Locator is an Anti-Pattern