17

Prism を使用したイベント集約の実装に取り​​組んでいます。いくつかのモジュールがあり、それぞれが要求されたときに通知するイベントにサブスクライブする必要があります。シェルでサブスクライブとパブリッシャーの両方を使用して、単純な例を作成することから始めました。問題ありません。今; サブスクライバーをモジュールに移動すると、トリガーされません。さらに奇妙なのは、実際に数回機能したことです。そのすべてがブレークポイントで保留されています。そのため、競合状態のように思えますが、その理由はわかりません。

仮定: IEventAggregator をどこにでもセットアップする必要はありません。たとえば、IoC コンテナーに登録しますか? これは Prism に組み込まれているため、イベント アグリゲーターのインスタンスは 1 つしかありません。

したがって、問題は基本的に、サブスクライバーをいつ、どこで、どのように設定する必要があるかです。ものなどに特定の順序はありますか?私の簡単な例では、1 つのモジュール 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");
}

これで、シェルにこのイベントを発行するボタンができました。シェルは、解決時に同じ (?) イベント アグリゲーターを取得します。

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

ノート:

  • イベントが公開されていることを確認しました。シェルにもサブスクライバーを追加すると、このサブスクライバーはイベントを受信します。
  • また; MyModule のサブスクライバーはトリガーされません。しかし、奇妙なことに、それは数回ありました。
  • イベントへの入力は使用しません。入力型が必要なようだったので、ダミーの bool を使用しました。これを取り除くことはできますか..?
4

2 に答える 2

31

Prism Event Aggregator は、弱参照を使用してイベントにリンクします。これは、イベント ハンドラからのメモリ リークを防ぐためです。

モジュール初期化子が実行されると破棄されるため、イベントが発生する前にイベント ハンドラーが破棄されます。サブスクライブのオーバーロードを使用して、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 に答える