17

我正在使用 Prism 实现事件聚合。我有几个模块,我希望他们每个人都订阅事件,告诉他们什么时候被请求。我开始在 shell 中使用订阅和发布者做一个简单的示例。那里没有问题。现在; 当我将订阅者移到我的模块时,他们不会被触发。更奇怪的是它实际上已经工作了几次——所有这些我都在断点处等待。所以在我看来这是一些比赛条件,但我不明白为什么。

假设:我不需要在任何地方设置 IEventAggregator - 例如在 IoC 容器中注册?这是内置在 Prism 中的,因此我只有一个事件聚合器实例,对吗?

所以,问题基本上是我应该如何/在哪里/何时设置我的订阅者。东西等有特定的顺序吗?在我的简化示例中,我有一个模块 MyModule。Bootstrapper 会将 MyModule 添加到目录中 - 使其初始化:

catalog.AddModule(typeof(MyModule));

MyModule 将存储聚合器并使用它来订阅 MyModuleRequestedEvent。它还使用菜单注册表在应用程序菜单中注册。这个想法是最终点击菜单应该触发事件 - 通知 MyModule 它已被请求。然后我希望 MyModule 有责任弄清楚下一步该做什么。

public MyModule(IEventAggregator aggregator, IApplicationMenuRegistry menu)
{
    _applicationMenu = menu;
    _aggregator = aggregator;
}

public void Initialize()
{
    var evnt = _aggregator.GetEvent<MyModuleRequestedEvent>();
    evnt.Subscribe(MyModuleRequested);
    _applicationMenu.RegisterMenuItem("MyModule", evnt);
}

public void MyModuleRequested(bool b)
{
    MessageBox.Show("MyModule requested");
}

现在,我的 shell 中有一个按钮,它将发布此事件。解析时,shell 会获得相同的 (?) 事件聚合器。

public Shell(IEventAggregator aggregator)
{
    InitializeComponent();
    var evnt = aggregator.GetEvent<MyModuleRequestedEvent>();
    EventTriggerButton.Click += (s, e) => evnt.Publish(true);
}

笔记:

  • 已验证事件已发布。在 shell 中添加订阅者也会使该订阅者接收事件。
  • 再次; MyModule 中的订阅者没有被触发。然而,奇怪的是,它已经出现过几次了。
  • 我不使用事件的输入。似乎您需要一些输入类型,所以我只使用了一个虚拟布尔值。我可以摆脱这个..?
4

2 回答 2

31

Prism 事件聚合器使用弱引用链接到事件。这是为了防止事件处理程序的内存泄漏。

一旦模块初始化程序运行,它就会被释放,因此您的事件处理程序在事件被触发之前被销毁。您可以通过使用订阅的重载来告诉 Prism 保留事件处理程序。

evnt.Subscribe(MyModuleRequested, true);

作为一种模式,我倾向于将任何事件订阅者放在一个单独的类中,并从模​​块的 Initialize 方法中调用该类。这样,当模块仍然被破坏时,事件仍然存在但分开。

于 2009-11-28T00:16:27.277 回答
2

所以,我只是得到了一个理论,但现在没有时间测试它..明天会做。

问题:将模块添加到 ModuleCatalogue 会使它们保持活力吗?我以为会的。因此 - MyModule 应该保持活动状态 - 然后将在事件发布时触发。

protected override IModuleCatalog GetModuleCatalog()
{
    var catalog = new ModuleCatalog();
    catalog.AddModule(typeof(MyModule));
    return catalog;
}

但是,如果这不能使模块保持活动状态,那么很明显它将很难响应事件。模块对象死了,但它没有取消订阅——因此我会在 EventAggregator 列表中看到订阅者,但订阅者已经不在了。还; 我提到它实际上偶尔会起作用 - 如果垃圾收集器在事件触发之前没有时间取出垃圾,就会出现这种情况。

这听起来像吗?如果是这样 - 我还没有想到解决方案,所以欢迎您在不同的回复线程中提出一个建议..

所以; ModuleCataloge 到底是什么?只是为初始化而保留的列表然后丢弃?

于 2009-11-27T23:33:56.893 回答