Unity解决循环依赖

在学习Unity(C#中的DI框架)的过程中,我遇到了一个类具有ClassB的setter注入的情况

class ClassA : IClassA { ... [Dependency] public IClassB ClassB { get { return _classB; } set { if (value == null) throw new ArgumentNullException("value"); _classB = value; } } 

另一个有ClassA的构造函数注入

 class ClassB : IClassB { ... [InjectionConstructor] public ClassB(IClassA classA) { _classA = classA; } } 

我无法在容器中正确解析这两个类。

  var container = new UnityContainer(); container.RegisterType(); container.RegisterType(); IClassA classA = new ClassA(); var instance = container.Resolve(); instance.DoSomethingFromClassB(); log.Info("Constructor Injection"); var instanceB = container.Resolve(); instanceB.DoSomethingFromClassA(); 

这给了我一个堆栈溢出exception

我尝试了解决这个问题的不同顺序,但它似乎没有用。

我这是可行的还是我只是在浪费时间。 这里究竟发生了什么。

像Unity这样的DI框架工作的方式是,当你调用它们实例化一个类时,它们递归地实例化传递给该类的构造函数(或由属性设置)的所有类。 这些类遵循相同的function,因此您可以看到如何创建无限循环的递归。 当Unity需要A时需要B和B时,Unity如何构建A? 两者都无法建造。

在大多数DI框架中,您无法解析共同依赖的类。 这是一个糟糕的设计模式AKA代码气味。 在经典意义上,如果ClassA需要了解ClassB ,而ClassB作为回报需要了解ClassA ,那么现实是它们共同关注并且应该组合成单个类ClassC 。 由于在这种情况下没有关注点分离,因此将它们分成两个单独的类,你什么都得不到。

像Unity这样的DI用于推广控制反转的模式,它只适用于类具有单向依赖性(不需要彼此了解)的情况。

我同意@Haney 这是一种代码味道 ,但技术上可行……

只需通过Lazy更改要解析的引用类型之一。 然后它实际上不解析该类型,直到它被使用,这将打破无限递归循环。

 class ClassB : IClassB { ... [InjectionConstructor] public ClassB(Lazy classA) { _classA = classA; } }