Prism Event Aggregation - 未触发订阅者

sti*_*k81 16 .net wpf prism eventaggregator

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

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

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

catalog.AddModule(typeof(MyModule));
Run Code Online (Sandbox Code Playgroud)

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");
}
Run Code Online (Sandbox Code Playgroud)

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

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

笔记:

  • 已验证该事件已发布.在shell中添加订户也会使该订户接收该事件.
  • 再次; MyModule中的订户未被触发.然而,奇怪的是,有几次.
  • 我没有使用事件的输入.看起来你需要一些输入类型,所以我只是带着一个虚拟布尔.我可以摆脱这个......?

Cam*_*and 30

Prism Event Aggregator使用弱引用链接到事件.这是为了防止事件处理程序的内存泄漏.

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

evnt.Subscribe(MyModuleRequested, true);
Run Code Online (Sandbox Code Playgroud)

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