Dot-Net

Prism 事件聚合 - 未觸發訂閱者

  • November 28, 2009

我正在使用 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 中的訂閱者沒有被觸發。然而,奇怪的是,它已經出現過幾次了。
  • 我不使用事件的輸入。似乎您需要一些輸入類型,所以我只使用了一個虛擬布爾值。我可以擺脫這個..?

Prism 事件聚合器使用弱引用連結到事件。這是為了防止事件處理程序的記憶體洩漏。

一旦模組初始化程序執行,它就會被釋放,因此您的事件處理程序在事件被觸發之前被銷毀。您可以通過使用訂閱的重載來告訴 Prism 保留事件處理程序。

evnt.Subscribe(MyModuleRequested, true);

作為一種模式,我傾向於將任何事件訂閱者放在一個單獨的類中,並從模組的 Initialize 方法中呼叫該類。這樣,當模組仍然被破壞時,事件仍然存在但分開。

引用自:https://stackoverflow.com/questions/1810730