棱镜事件汇总 - 用户不会被触发棱镜、事件、用户

2023-09-03 06:28:47 作者:暖暖

我正在实现一个事件汇总与棱镜。我有几个模块,并且我希望他们每个人来订阅事件,告诉他们在需要的时候。我开始做一个全平的例子既认购和发行商的壳。有没有问题。现在;当我移动用户写给我的模块,他们不被触发。什么是更奇怪的是,它居然曾几次 - 所有这一切我已经挂起的断点。所以,在我看来是一些竞争状态,但我不明白为什么。

I'm working on implementing an event aggregation with Prism. I have a few modules, and I want each of them to subscribe to events that tells them when they are requested. I started out doing an all plain example with both subscribed and publisher in the shell. No problems there. Now; when I move the subscribers out to my modules they don't get triggered. What's even more odd is that it actually has worked a few times - all of which I've been pending in a breakpoint. So it seems to me to be some race condition, but I don't understand why.

假设做:的我不需要建立IEventAggregator任何地方 - 例如:注册在IoC容器?这是内置于棱镜,这样我只有事件聚合的一个实例,对不对?

Assumption made: I don't need to set up the IEventAggregator anywhere - e.g. registering in the IoC container? This is built into Prism such that I only have one instance of the event aggregator, right?

所以,问题基本上是如何/在哪里/我应该设置我的用户。是否有东西等特定的顺序?在我简单的例子,我有一个模块MyModule的。该引导程序将增加MyModule的到目录 - 使得它初始化:

So, the question is basically how/where/when I should set up my subscribers. Is there a specific order on stuff etc? In my simplified example I have one module MyModule. The Bootstrapper will add MyModule to the catalog - making it initialized:

catalog.AddModule(typeof(MyModule));

MyModule的将存储聚合器,并使用这个订阅的MyModuleRequestedEvent。它还采用了菜单注册表中的应用程序菜单中进行注册。我们的想法是,最终点击菜单应触发事件 - 通知MyModule的,它已被请求。然后,我想这是MyModule的负责找出进一步做。

MyModule will store the aggregator and use this for subscribing to the MyModuleRequestedEvent. It also uses a menu registry to register in the application menu. The idea is that eventually clicking in the menu should trigger the event - notifying MyModule that it has been requested. Then I want it to be MyModule's responsibility to figure out what to do further.

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");
}

现在,我已经在我的壳一个按钮,将发布此事件。外壳得到相同的(?)事件聚合时得到解决。

Now, I have a button in my shell which will publish this event. The shell gets the same (?) event aggregator when resolved.

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

注:

已验证事件发布。添加一个用户在外壳也会使该用户接收该事件。 同样,在MyModule的订户将不触发。但是,它有 - 奇怪 - 上过几次。 我不使用的输入事件。这似乎是你需要有一些输入型的,所以我只是去与一个虚拟的布尔。我可以摆脱这个..?

推荐答案

棱镜事件聚合器使用弱引用链接到的事件。这是prevent内存泄漏的事件处理程序。

The Prism Event Aggregator uses Weak References to link to the events. This is to prevent memory leaks from event handlers.

在一个模块初始化程序已运行它的处置,因此该事件被解雇之前,你的事件处理程序被破坏。你可以告诉棱镜通过订阅过载,以保持该事件处理程序周围。

Once a module initializer has been run it's disposed of, so your event handler is being destroyed before the event is being fired. You can tell Prism to keep the event handler around by using an overload of Subscribe.

evnt.Subscribe(MyModuleRequested, true);

作为一个模式,我倾向于把在一个单独的类中的任何事件的用户,并调用类从模块初始化方法。这样的事件,维持生命,但分开而模块仍遭到破坏。

As a pattern, I tend to put any event subscribers in a separate class, and call that class from the modules Initialize method. That way the events stay alive but separate while the module is still destroyed.