Prism Event Aggregation - 未触发订阅者

时间:2009-11-27 21:47:17

标签: .net wpf prism eventaggregator

我正在使用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中的订户未被触发。然而,奇怪的是,有几次。
  • 我不使用事件的输入。看起来你需要一些输入类型,所以我只是带着一个虚拟布尔。我可以摆脱这个......?

2 个答案:

答案 0 :(得分:30)

Prism Event Aggregator使用Weak References链接到事件。这是为了防止事件处理程序发生内存泄漏。

一旦模块初始化程序运行它就被处理掉了,所以你的事件处理程序在事件被触发之前就被销毁了。你可以通过使用Subscribe的重载来告诉Prism保持事件处理程序。

evnt.Subscribe(MyModuleRequested, true);

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

答案 1 :(得分:2)

所以,我刚刚得到了一个理论,但现在没时间对它进行测试..明天会做。

问题:在ModuleCatalogue中添加模块会让它们保持活力吗?我以为它会。因此 - MyModule应保持活跃状态​​ - 然后在事件发布时触发。

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

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

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

因此;无论如何,ModuleCataloge是什么?只是一个列表保留初始化然后扔掉?