【发布时间】:2013-02-24 05:50:03
【问题描述】:
假设我有两个类,但它们只能通过工厂创建,为了强制执行,我将工厂创建为它们正在创建的对象的内部类,以便它们可以访问私有构造函数。在这种情况下,一个类需要创建另一个类的实例,而第二个类需要创建第一个类的实例:
public class A
{
public class Factory
{
private readonly B.Factory bFactory;
public Factory(B.Factory bFactory)
{
this.bFactory = bFactory;
}
public A Build()
{
return new A(this.bFactory);
}
}
private A(B.Factory bFactory)
{
}
}
public class B
{
public class Factory
{
private readonly A.Factory aFactory;
public Factory(A.Factory aFactory)
{
this.aFactory = aFactory;
}
public B Build()
{
return new B(this.aFactory);
}
}
private B(A.Factory aFactory)
{
}
}
通常我会通过创建另一个名为 ABFactory 的工厂来解决这个问题,该工厂可以同时创建 A 和 B 实例,我会让 A 和 B 都声明对 ABFactory 的依赖,但在这种情况ABFactory 无法访问A 和B 的私有构造函数。
假设语义是正确的(在这种情况下,A 返回B 的实例和B 返回另一个A 的实例是合乎逻辑的)那么最好的方法是什么解决这个问题?
更新 1
到目前为止,我的解决方案是创建一个名为 CircularDependencyResolver 的新类。两个工厂中的每一个都声明依赖于它而不是另一个工厂。每个人都在自己的构造函数中向该解析器注册自己(this)。当他们去构建各自的对象时,他们会调用解析器上的Resolve 方法,该方法会寻找其他注册的工厂,或者抛出异常。
问题当然是我们已经推迟解决 A 或 B 的依赖关系,直到我们真正需要创建它,而不是在程序启动时,但它确实有效。
不过,我仍然对其他解决方案感兴趣。
【问题讨论】:
-
虽然有些容器可能支持这个,但我认为这基本上是一个设计缺陷。我总是会尝试重新设计以一起消除循环依赖。循环会在很多层面(GC、编译、实例化等)上导致问题,这通常是您不想承担的技术债务
-
@PeterRitchie - 即使我没有循环依赖(所以我有一个
ABFactory)我仍然不能让工厂调用两个私有构造函数。
标签: .net dependency-injection circular-dependency