- EventAggregator is なに?
- .NET アプリ開発に Prism EventAggregator をなぜ使用するのか?
- Prism EventAggregator をいつ利用するのか?
- Xamarin.Forms の EventAggregator
- ちょっとした注意点
- 参考
この記事は、ARCTOUCH のブログ記事「Why you should use Prism EventAggregator in .NET app development」を個人的に雑訳したものです。
EventAggregator
については「過去の記事」で紹介しています。
Prism は、.NET アプリを開発するための豊富な機能を提供するライブラリーで、C# 開発者のコーディングライフをより快適にする多くの優れた機能を備えています。その機能のひとつが EventAggregator
です。この記事では、EventAggregator
とはなにか、なぜ便利なのか、そして、どこで使うべきなのかを説明します。
EventAggregator is なに?
要するに、EventAggregator
とは Publisher-Subscriber パターンを Prism で実装したものです。Publisher-Subscriber パターンとは、アプリケーションの非同期通信を容易にするため設計されたメッセージングのパターンのことです。具体的には、リンクすることが困難なコンポーネント間でメッセージをやり取りするといった、問題を解決します。
このパターンの核となるものは、event bus に対して発行されるイベントです。event bus は、そのイベントを1つ以上のサブスクライバー (subscribers) に渡します。サブスクライバーは、受け取ったイベントを自由に扱うことができます。
より詳細な情報は「こちら」をご覧ください。
.NET アプリ開発に Prism EventAggregator をなぜ使用するのか?
Publisher-Subscriber モデルには、さまざまなメリットがあります:
- 分離 (Decoupled)
パブリッシャーとサブスクライバーはお互いのことを知りません - 非同期 (Asynchronous)
パブリッシャーは、サブスクライバーがイベントの処理を終えるまで待つ必要がないので、メッセージを素早く送信し、自分の処理を続けることができる - 関心の分離 (Separation of concerns)
パブリッシャーはサブスクライバーが何をしているのか知る必要はありません。また、サブスクライバーはイベントがどこで発生したのか知る必要はありません。 - 拡張性 (Scalable)
パブリッシャー、サブスクライバー、イベントの数がどれだけ多くても、必要なのは、ひとつのイベントバスへの参照だけ
EventAggregator
は、上記の利点に加えて .NET アプリの開発に役に立つ利点を持ちます:
- メモリーリークの防止 (Prevent memory leaks)
EventAggregator
は、廃棄されたサブスクライバの参照を保持しません。マニュアルでサブスクライブを解除する必要もありません - 複雑なオブジェクトの送信 (Send complex objects)
イベントを発行する際に複雑なオブジェクトをパラメーターとして送信して、イベントを処理する際にサブスクライバーにより多くの情報を提供する - スレッドの柔軟性 (Thread flexibility)
受信したイベントを処理するスレッドを選択できる - イベントのフィルタリング (Filter events)
サブスクライバーは、処理するイベントと無視するイベントを選択できる
Prism EventAggregator をいつ利用するのか?
要約すると、Publisher-Subscriber パターンは、リンクすることが難しい、または、現実的ではないコンポーネント間の通信用に設計されたメッセージングのパターンです。
Prism のプロジェクトでは、EventAggregator
は、2つ以上の ViewModel の間や、お互いに参照を持たないサービスの間でメッセージを送受信するためによく利用されます。
また、1つのイベントを異なる多くのサブスクライバーで処理する必要があって、それぞれのサブスクライバーにパブリッシャーの参照を渡さない(現実的ではない)ときにも利用されます。
Xamarin.Forms の EventAggregator
Xamarin.Forms に慣れている人は、「待って、Xamarin.Forms には、これに似たものがすでにあるんじゃないか?」と思うかもしれません。確かに、Xamarin.Forms には MessagingCenter
という独自の Publisher-Subscriber パターンの実装があります。しかし、以下の理由から私は Prism の EventAggregator
が気に入っています:
- メモリーリーク (Memory leaks)
MessagingCenter
は、マニュアルでサブスクライブを解除しないと、参照を保持します。(「Xamarin MessagingCenter memory leaks」で検索すると、パフォーマンスの問題に関する多くのフォーラム投稿を見つけることができます) - 柔軟性 (Flexibility)
MessagingCenter
は、EventAggregator
のようなスレッドの柔軟性やイベントフィルターはありません - テストの容易性 (Testability)
MessagingCenter
は、static メソッドを使用しているため、単体テストの作成が難しいです。Prism では、コンストラクターにEventAggregator
のインスタンスを注入することができるので、簡単にモックを作成することができます
ちょっとした注意点
ここまでの内容で EventAggregator
の柔軟性や有用性について、納得していただけたなら幸いですが、(いつものように、)いくつかの注意点があります。
EventAggregator
はサブスクライバーへの弱参照しか持ちませんが、パブリッシャーがパラメーターを渡し、サブスクライバーがその参照を持ち続けている場合は強参照として持つ恐れがあります。このような場合は、サブスクライバーが disposed されたときにマニュアルでサブスクライブを解除するようにしましょう。
また、EventAggregator
の Decoupled な(分離された)構造は素晴らしいものですが、使いすぎると複雑さが増してしまいます。
パブリッシャーとサブスクライバーの間には関心の分離がありますが、イベント自体は関心の分離がありません。(イベントは、すべて同じ EventAggregator
に保持されます)
多くのイベントを扱う大きなプロジェクトでは、これがコミュニケーションの流れを不明瞭にする恐れがあります。私のアドバイスとしては、EventAggregator
は、必要なときにだけ使うようにしましょう。プロジェクト全体を EventAggregator
を中心に構築することはやめておきましょう。
なんでもそうですが、節度を守ることが大切です。(Like with everything in life, moderation is key.)