通过IoC将依赖项提供给工厂类?

Mit*_*h A 4 configuration factory spring.net inversion-of-control

我有一个工厂类,它决定它应该实例化和返回的四个可用子类中的哪一个.正如您所料,所有子类都实现相同的接口:

public static class FooFactory{
     public IFoo CreateFoo(FooEnum enum){
            switch (enum)
            {
                case Foo1:
                    return new Foo1();
                case Foo2:
                    return new Foo2();
                 case Foo3:
                    return new Foo3(IBar);//has a constructor dependency on IBar
                case Foo4:
                    return new Foo4();
                 default:
                    throw new Exception("invalid foo!");
            }
     }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,其中一个子类在其构造函数中定义了依赖项.

一些兴趣点:

  • 我们使用Spring.NET作为IoC.
  • 所有子类IFoo都是域对象,因此不会被Spring.NET实例化.如果可能的话,我想保持这种方式.
  • 该应用程序有一个手写的数据访问层(呕吐),因此这里没有ORM.

我试图找出如何最好地将IBar依赖关系传递Foo3FooFactory.我觉得这可能是通过IoC最好解决的问题,但我不能理解如何.我还希望尽可能保持FooFactory单元可测试:即我不希望在测试代码中依赖Spring.NET.

谢谢阅读.

Mar*_*ann 6

将FooFactory更改为抽象工厂并将IBar实例注入具体实现,如下所示:

public class FooFactory : IFooFactory {
     private readonly IBar bar;

     public FooFactory(IBar bar)
     {
         if (bar == null)
         {
             throw new ArgumentNullException("bar");
         }

         this.bar = bar;
     }

     public IFoo CreateFoo(FooEnum enum){
            switch (enum)
            {
                case Foo1:
                    return new Foo1();
                case Foo2:
                    return new Foo2();
                 case Foo3:
                    return new Foo3(this.bar);
                case Foo4:
                    return new Foo4();
                 default:
                    throw new Exception("invalid foo!");
            }
     }
}
Run Code Online (Sandbox Code Playgroud)

请注意,FooFactory现在是实现IFooFactory接口的具体非静态类:

public interface IFooFactory
{
    IFoo CreateFoo(FooEnum emum);
}
Run Code Online (Sandbox Code Playgroud)

在您需要IFoo实例的代码中的任何地方,您将依赖于IFooFactory并使用其CreateFoo方法来创建所需的实例.

您可以使用任何值得盐的DI容器连接FooFactory及其依赖项.

  • @Sky Sanders:最好避免在工厂内安装DI容器.工厂是一个像其他任何东西的域对象,并且在域对象中有容器导致服务定位器反模式:http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx (2认同)