循环依赖注入

本文关键字:注入 依赖 循环 | 更新日期: 2023-09-27 18:10:33

让我有两个非常基本的对象,如:

public class View
{
    public View(Controller controller)
    {
        // Use the model exposed by the controller here
    }
}
public class Controller
{
    private readonly IView view;
    public Controller()
    {
        this.view = new View(this);
    }
    public Controller(View v)
    {
        this.view = v;
    }
}

后来我决定通过DI注入视图对象到控制器中,但我有一个循环依赖(即我不能使用var ctrl = new Controller(new View(ctrl));)。在这种情况下如何注入依赖呢?

循环依赖注入

最常见的解决方案是使用依赖属性来解决循环依赖。例如,在其中一个类中创建一个新属性,并让IoC容器为其赋值。

如果你使用Unity,你应该将[Dependency]添加到该属性。

旁注:视图不应该依赖于控制器。它根本不应该意识到这一点。

回复评论

你不能。这就是循环依赖的问题。唯一的其他解决方案是使用组合。这就是将公共功能分解成一个单独的类,并将其包含在控制器和视图中。

我发现了一个使用Ninject的很好的解决方案。

public class Controller
{
    private readonly View view;
    public Controller(ViewModule viewModule)
    {
        using (IKernel kernel = new StandardKernel(viewModule))
        {
            this.view = kernel.Get<View>(new ConstructorArgument("controller", this);
        }
    }
}

其中ViewModule是一个预配置的Ninject模块来解决特定的视图依赖(GUI, CLI等)这里的小问题是,我现在依赖于特定的DI框架

在构造器注入中根本不能这样做如果将控制器的构造函数更改为

public Controller(IView view)

以什么顺序创建这两个对象?视图需要控制器Instance,控制器需要视图。但是,您可以将控制器的IView属性设置为公共,并在创建后设置该属性(当您设置正确的属性时,一些di - container可以自动为您完成此操作)。