Winforms 使用Windsor castle进行依赖注入的MVP模式中的循环引用问题

Winforms 使用Windsor castle进行依赖注入的MVP模式中的循环引用问题,winforms,dependency-injection,castle-windsor,mvp,Winforms,Dependency Injection,Castle Windsor,Mvp,在使用windsor容器创建以下MVP设计(针对winforms)时,我面临循环依赖性问题 我的演示者取决于视图和模型: ConcretePresenter(IView view, IModel model) { this.view = view; this.model = model; } 我的视图取决于演示者: ConcreteView(ConcretePresenter presenter) { //actual requirement that the pres

在使用windsor容器创建以下MVP设计(针对winforms)时,我面临循环依赖性问题

我的演示者取决于视图和模型:

ConcretePresenter(IView view, IModel model)
{
    this.view = view;
    this.model = model;
}
我的视图取决于演示者:

ConcreteView(ConcretePresenter presenter)
{
    //actual requirement that the presenter use the current instance of the view and a model object 
    //new presenter(this, new model()) 
    this.presenter = presenter;
}
// Presenter
ConcretePresenter(IModel model)
{
    this.model = model;
}

public IView View { get; set; }

// View
ConcreteView(ConcretePresenter presenter)
{
    this.presenter = presenter;
    this.presenter.View = this;
}
我正在使用Windsor castle(在单独的合成根类中)注册所有组件,如下所示:

IWindsorContainer container;
container = new WindsorContainer();
container.Register(Component.For<ConcretePresenter>().ImplementedBy<ConcretePresenter>());
container.Register(Component.For<IModel>().ImplementedBy<ConcreteModel>());                      
container.Register(Component.For<IView>().ImplementedBy<ConcreteView>()); 
IWindsorContainer;
容器=新WindsorContainer();
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
解决视图会带来循环引用问题:

container.Resolve<ConcreteView>(); //doesn't resolve because of cyclic dependency
container.Resolve()//由于循环依赖关系而无法解析
一个可能的解决方案是从视图中删除构造函数注入,并单独解析演示者。 但这会导致我在两个地方使用容器,而我并不打算这样做,而且可能是错误的。

ConcreteView()
{
    container.Resolve<ConcretePresenter>(); //resolving at 2 different points       
}
ConcreteView()
{
container.Resolve();//在两个不同点进行解析
}

有没有更好的解决办法。我在MVP本身做了什么错事吗?

创建一个工厂来实例化演示者。您的视图(WinForm)将使用构造函数中的工厂。您可能可以使用类型化工厂设施——这意味着您只需为presenter工厂定义接口,并让该设施完成其余工作。

有几种解决方案可以解决此问题,但所有这些解决方案都可以通过将presenter或视图从as构造函数依赖项中删除来打破依赖关系循环

最简单的解决方案是在演示者上引入view as属性:

ConcreteView(ConcretePresenter presenter)
{
    //actual requirement that the presenter use the current instance of the view and a model object 
    //new presenter(this, new model()) 
    this.presenter = presenter;
}
// Presenter
ConcretePresenter(IModel model)
{
    this.model = model;
}

public IView View { get; set; }

// View
ConcreteView(ConcretePresenter presenter)
{
    this.presenter = presenter;
    this.presenter.View = this;
}
这样做的缺点是,在将每个演示者注入视图时,您需要对其进行配置,因此您还可以将其移动到基类:

// View
ConcreteView(ConcretePresenter presenter) : base(presenter)
{
}

BaseView(IPresenter presenter)
{
    Contract.Requires(presenter != null);
    presenter.View = this;
    this.Presenter = presenter;
}
另一个选项是将presenter factory插入到视图中,并从视图中请求它:

// View
ConcreteView(IPresenterFactory factory)
{
    this.presenter = factory.CreatePresenterFor(this);
}

缺点是此构造函数调用工厂,这不是最干净的操作,但可以管理。

可能重复:我使用了您建议的第一个选项,它对我很有效。我认为这是一个糟糕的Di,因为将注入从复合根移动到另一个点。