我使用MVP模式创建通过工厂加载到Shell中的视图模块:
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 Event Aggregator触发事件来填充模块。然而,我发现它永远不会填充。我的结论是主持人(处理事件)正在收集垃圾,因此发布的事件被置若罔闻。我通过创建一个析构函数并对其进行破坏来证实了这一点。
我可以找出可能的解决方案,但它们带有警告:
1)我想过将KeepSubscriberReferenceAlive
设为true,但another SO answer states this should be a rare occurrence。
2)我可以给view
presenter
提及view
,但我在营地认为ViewModuleFactory
应该完全愚蠢而且没有提及主持人。
3)我可以为Presenter
提供ViewFactory
字段引用。工厂在程序的生命周期内保持活力,因此主持人参考被保留,但我觉得可能完全打开另一种蠕虫。
什么是真的奇怪的是我在{{1}}中有另一个模块以完全相同的方式加载,但不知何故,演示者没有最终确定如此。
任何帮助都将不胜感激。
答案 0 :(得分:1)
在使用模型 - 视图 - 演示者模式时我遇到过类似的问题,在我看来,选项2是最简单的方法。
你可以在没有视图的情况下做到这一点并且知道'通过让所有视图实现以下基本界面来了解具体的演示者:
public interface IView
{
object Presenter { set; }
}
当您使用WinForms时,您可以拥有一个实现IView
接口的基类,并将presenter对象存储在Tag
属性中。
public abstract class ViewBase : UserControl, IView
{
public object Presenter
{
set { this.Tag = value; }
}
}
然后可以更新您的演示者基类以设置IView.Presenter
属性并将其自身传递给视图以确保引用保持活动,例如。
public class Presenter
{
public Presenter(View view)
{
view.Presenter = this;
}
}
或者,您的视图类可以直接保存对presenter对象的引用,如下所示:
public abstract class ViewBase : UserControl, IView
{
private object _presenter;
public object Presenter
{
set { this._presenter = value; }
}
}
虽然你的视图类现在有一个对演示者的引用,但是他们不知道演示者的实际具体类型,只要该字段是私有的,子类就不能以任何方式实际检索和使用演示者,所以这只会变成框架的实现细节,用于将演示者的生命周期与其关联视图的生命周期联系起来。