c# - 保持演示者引用处于事件状态,而不提供对其控制的 View 的引用

标签 c# winforms events garbage-collection mvp

我使用 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/

相关文章:

C# byte 与 int 短整数值

c# - fileupload控件在updatepanel下时如何上传图片?

c# - 通过 Console/WinForms 中的 ServiceHost 托管 WCF 服务

.net - Winforms - 单击/拖动表单中的任意位置以移动它,就像在表单标题中单击一样

javascript - 为什么从 Backbone 中的自定义 BaseView 扩展时, 'events' 没有绑定(bind)到 View ?

c# - 如何在 .NET 中加密字符串?

c# - 正则表达式匹配除 5 之外的所有数字字符

C# 显示表格中的某些行

javascript - 有人可以向我解释 Dojo 的 '' dojo/on”模块中到底发生了什么吗?

javascript - 我需要在 2016 年删除事件监听器吗?