Prism コードサンプル学習:14-UsingEventAggregator
はじめに
以下の記事の続きです。
https://qiita.com/mngreen/items/787f8f92e2da3c787770
14-UsingEventAggregator
本サンプルは、互いに依存していないモジュール間でメッセージを送受し、連携して動作することを確認するサンプルとなっています。
UsingEventAggregator.Coreではモジュール間で共通して利用されるMessageSentEventクラスを定義しています。
using Prism.Events;
namespace UsingEventAggregator.Core
{
public class MessageSentEvent : PubSubEvent<string>
{
}
}
PubSubEvent<T>はEventBaseクラスを継承していて、内部的には購読者をコレクションとして保持していることがわかります。
Subscribeの実処理では、まずはじめにActionReferenceを生成しています。渡されたアクションからそのアクションの持ち主であるインスタンスを特定しています。
その後、それぞれのオプションによって生成されるインスタンスが異なりますが、基本的に利用されそうなEventSubscriptionクラスでは、必要に応じてアクションを実行するか否かを決める処理(GetExecutionStrategy)が重要そうでした。
上記のメソッドがどこで利用されるかというと、EventBaseクラスのInternalPublishメソッド内にあるPruneAndReturnStrategiesメソッドです。この中で実行対象が抽出されます。
上記のイベントをModuleAは発行、ModuleBは購読しているのが以下のコードです。
namespace ModuleA.ViewModels
{
public class MessageViewModel : BindableBase
{
IEventAggregator _ea;
private string _message = "Message to Send";
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
public DelegateCommand SendMessageCommand { get; private set; }
public MessageViewModel(IEventAggregator ea)
{
_ea = ea;
SendMessageCommand = new DelegateCommand(SendMessage);
}
private void SendMessage()
{
// イベントアグリゲーターからイベントを取得してメッセージを発行する
_ea.GetEvent<MessageSentEvent>().Publish(Message);
}
}
}
namespace ModuleB.ViewModels
{
public class MessageListViewModel : BindableBase
{
IEventAggregator _ea;
private ObservableCollection<string> _messages;
public ObservableCollection<string> Messages
{
get { return _messages; }
set { SetProperty(ref _messages, value); }
}
public MessageListViewModel(IEventAggregator ea)
{
_ea = ea;
Messages = new ObservableCollection<string>();
// イベントアグリゲーターを経由して、イベントを購読している
_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);
}
private void MessageReceived(string message)
{
Messages.Add(message);
}
}
}
EventAggregatorでは型をキー、イベントをバリューとするディクショナリーを保持しており、要求に応じてイベントを返します。
EventAggregator自体は全体で46行ほどしかなく、GetEvent<TEventType>メソッドを公開しているのみで非常にシンプルな作りになっています。
おわりに
今回はEventAggregatorの使い方と、そのライブラリ内部の実装を読んでみました。
EventAggregatorを利用することで、結合が疎であるモジュール間でもうまく連携できそうです。
また、APIをシンプルに保つための工夫として、Actionの持ち主であるインスタンスを引数にわたすのではなく、Actionからインスタンスを探し出す方法を採用しているのは、勉強になりました。
次回、15-FilteringEventsについて見ていこうと思います。