我使用 MVP 模式来创建通过工厂加载到 Shell 中的 View 模块:
public class ViewModuleFactory : IViewModuleFactory
{
private readonly IEventAggregator Events;
public ViewModuleFactory(IEventAggregator Events)
{
this.Events = Events;
}
public Control CreateModule()
{
var view = new View();
var presenter = new Presenter(Events, view);
return view;
}
}
在 shell 中加载模块后,我通过 Prism 事件聚合器触发一个事件来填充模块。然而,我发现它永远不会填充。我的结论是,演示者(处理事件)正在被垃圾收集,因此发布的事件被置若罔闻。我已经通过创建析构函数并对其设置断点来确认这一点。
我可以确定可能的解决方案,但它们有一些警告:
1) 我想将 KeepSubscriberReferenceAlive
设置为 true,但是 another SO answer states this should be a rare occurrence .
2) 我可以为 view
提供对其 presenter
的引用,但我认为 view
应该是完全愚蠢,并且没有提及演示者。
3) 我可以为 ViewModuleFactory
提供对 Presenter
的字段引用。工厂在程序的生命周期中保持事件状态,因此演示者引用得以保留,但我觉得这可能会完全打开另一个蠕虫 jar 。
真正奇怪的是,我在 ViewFactory
中有另一个模块,它以完全相同的方式加载,但不知何故,演示者没有像这个那样最终确定。
如有任何帮助,我们将不胜感激。
最佳答案
我在使用模型- View -演示者模式时也遇到过类似的问题,我认为选项 2 是最简单的方法。
通过让所有 View 实现以下基本接口(interface),您可以在 View “不知道”具体演示者的情况下完成此操作:
public interface IView
{
object Presenter { set; }
}
当您使用 WinForms 时,您可以拥有一个实现 IView
接口(interface)并将演示者对象存储在 Tag
属性中的基类。
public abstract class ViewBase : UserControl, IView
{
public object Presenter
{
set { this.Tag = value; }
}
}
然后可以更新您的演示者基类以设置 IView.Presenter
属性并将其自身传递给 View 以确保引用保持事件状态,例如
public class Presenter
{
public Presenter(View view)
{
view.Presenter = this;
}
}
或者,您的 View 类可以直接保存对演示者对象的引用,如下所示:
public abstract class ViewBase : UserControl, IView
{
private object _presenter;
public object Presenter
{
set { this._presenter = value; }
}
}
尽管您的 View 类现在拥有对演示者的引用,但它们不知道演示者的实际具体类型,并且只要该字段是私有(private)的,子类实际上就无法以任何方式检索和使用演示者,因此这只是变成框架的实现细节,用于将演示者的生命周期与其关联 View 的生命周期联系起来。
关于c# - 保持演示者引用处于事件状态,而不提供对其控制的 View 的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21763490/