处理IOC中的循环依赖关系

时间:2009-01-27 07:44:42

标签: design-patterns inversion-of-control

我正在尝试使用IOC容器在我的应用程序中创建初始对象图。

我有一个MainForm。此表单取决于MenuStrip,它取决于多个MenuStripItems。一些MenuStripItems依赖于MainForm。

目前我为构造函数注入设置了所有依赖项。显然,解析MainForm现在会导致堆栈溢出,因为MainForm的MenuStripItem依赖关系尝试解析Mainform等等......

解决此循环依赖的最佳方法是什么?

7 个答案:

答案 0 :(得分:5)

无论您是否使用IoC,循环依赖都是设计糟糕的表现。我建议你重新设计以避免它。添加辅助对象可能是一种解决方案。

例如,使MenuStripItems仅依赖于MainForm的一部分,而不是整体而言。

答案 1 :(得分:3)

创建一个控制器类,它提供MainForm和MenuStripItem都需要避免循环引用的数据和逻辑。

答案 2 :(得分:3)

您可以使用setter在构造之后注入一些依赖项。

答案 3 :(得分:3)

我同意kgiannakakis:

  

循环依赖是一个标志   糟糕的设计,无论你使用的是什么   IoC与否。我建议你做一个   重新设计以避免它。添加帮助器   对象可能是一种解决方案。

要找出应该将哪些方法提取到帮助程序类中,此过程可能有所帮助:

假设你有一个A类和一个B类相互引用并创建一个循环依赖。 要找出要提取到外部帮助器中的方法,请列出类A使用的类A中的所有方法,以及类A使用的类B中的所有方法。两个列表中较短的一个是隐藏的帮助器C级。

灵感来自MiškoHeveryhttp://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

答案 4 :(得分:1)

我没有看到创建辅助类或控制器如何解决循环依赖问题。

我会提供更多细节。 MenuStripItems依赖于MainForm,因为它们可以设置MainForm的内容。根据上述建议,假设我为MainForm Content,IFormContent创建了一个单独的界面。 然后MenuStripItem可以依赖于IFormContent。 但是,IFormContent的实现将再次依赖于MainForm,从而导致循环依赖。

也许我应该在某处使用setter注入而不是构造函数注入?

答案 5 :(得分:1)

您需要创建一个经销商类(或接口),其中包含您正在使用它们的类的引用。您应该使用此经销商类(或接口),而不是之前尝试使用它们的每个引用类。

解释解决方案:
考虑以下3个课程:

public Class A {
    public Method CommonMethod(){
        //Some implementation...
    }

    Method C(){
        //CommonMethod form class B are using here
        B obj = new B();
        B.CommonMethod();
    }
}


public Class B {
    public Method CommonMethod(){
        //Some implementation...
    }

    Method D(){
        //CommonMethod form class A are using here
        A obj = new A();
        A.CommonMethod();
    }
}


public Class DealerClass {
    private readonly A _inctanceA;
    private readonly B _inctanceB;

    //Cunstructor method of the class
    DealerClass(A inctanceA, B inctanceB){
        _inctanceA = inctanceA;
        _inctanceB = inctanceB;
    }

    //Using CommonMethod of class A
    public UsingCommonMethodA(){
        _inctanceA.CommonMethod();
    }

    //Using CommonMethod of class B
    public UsingCommonMethodB(){
        _inctanceB.CommonMethod();
    }    
}

因此,根据此解决方案,您应该使用 DealerClass 中具有循环依赖关系的其他类的方法。

答案 6 :(得分:0)

如何创建MenuStrip和MenuStripItem?

当我使用IOC时,服务与IOC容器为服务提供的依赖关系之间始终存在一对一的关系。如果某个服务需要多个项目,那么它将与创建多个项目的单个工厂对象具有一对一的关系。可以对此工厂方法进行参数化,以允许创建的项目返回其容器。