循环依赖 - 注入直接依赖的对象

问题描述:

我已经使用骰子PHP DI容器 一段时间了似乎在注入依赖关系的简单性方面是最好的。

I have used Dice PHP DI container for quite a while and it seems the best in terms of simplicity of injecting dependencies.

骰子文档

class A {
    public $b;

    public function __construct(B $b) {
        $this->b = $b;
    }
}

class B {

}

$dice = new \Dice\Dice;    
$a = $dice->create('A');
var_dump($a->b); //B object

但是,当您必须使用直接相互依赖的对象时,最终的结果是服务器错误,因为无限循环

However, when you have to use objects that are directly dependent on each other, the finall result is server error, because of the infinite loop.

示例:

class A {
    public $b;

    public function __construct(B $b) {
        $this->b = $b;
    }
}

class B {
    public $a;

    public function __construct(A $a) {
        $this->a = $a;
    }
}

骰子的作者说没有办法从A或B类构造一个对象。作为:

Author of Dice says that there is no way to construct an object from the A or B classes. As:


  • 'A'对象在创建之前需要一个'B'对象存在


作者说,这个对象需要一个A对象存在才能创建限制关注全部 DI容器

Author says, that this limitation concerns all DI containers!

在不更改初始代码的情况下,什么是克服这个问题的最佳解决方案 ?任何人都可以提供使用其他 DI容器的示例,当可以运行示例代码 而不使用 解决方法?

What would be the best solution for overcoming this problem nicely without changing initial code? Could anyone provide an example of using other DI containers, when it would be possible to run exampled code without bulky workarounds?

正如您在Dice github上发表的( https://github.com/TomBZombie/Dice/issues/7 ),解决而不去除循环依赖的唯一方法是重构一个使用setter注入的类:

As mentioned on your post on the Dice github ( https://github.com/TomBZombie/Dice/issues/7 ), the only way to resolve without removing the circular dependency is to refactor one of the classes to use setter injection:

class A {
    public $b;

    public function __construct(B $b) {
        $this->b = $b;
    }
}


class B {
    public $a;

    public function setA(A $a) {
        $this->a = $a;
    }
}

这允许构建对象:

$b = new B();
$a = new A($b);
$b->setA($a);

使用原始代码:

class A {
    public $b;

    public function __construct(B $b) {
        $this->b = $b;
    }
}

class B {
    public $a;

    public function __construct(A $a) {
        $this->a = $a;
    }
}

你不能构建它,遇到同样的问题容器:

You cannot construct it and run into the same problem as the container:

$b = new B(new A(new B(new A(new B(.............))))

有容器解决这个问题使用诸如ReflectionClass :: newInstanceWithoutConstructor之类的问题是,您的对象现在依赖于使用此方法的创建逻辑,您基本上将代码耦合到容器,这是一个糟糕的设计,因为您的代码现在不再可移植,无法使用没有容器来执行对象构造。

The problem with having a container work around this issue using a hack such as ReflectionClass::newInstanceWithoutConstructor is that your objects are now dependent on creation logic which uses this method. You essentially couple the code to the container which is a poor design as your code is now no longer portable and cannot be used without the container to perform the object construction.