繁体   English   中英

Unity解决循环依赖

[英]Unity resolving cyclic dependency

在学习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<IClassB, ClassB>();
container.RegisterType<IClassA, ClassA>();
IClassA classA = new ClassA();
var instance = container.Resolve<ClassA>();
instance.DoSomethingFromClassB();

log.Info("Constructor Injection");
var instanceB = container.Resolve<ClassB>();
instanceB.DoSomethingFromClassA();

这给了我一个堆栈溢出异常

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

我这是可行的还是我只是在浪费时间。

这里到底发生了什么?

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM