Home > C# > Toolkit > UIパターン > Prism > ドキュメント

9: Prism Library 5.0 for WPFを使用して、疎く結合したコンポーネントの間の情報をやりとりする

新規作成日 2016-06-19
最終更新日
※訳注 Visual Studio Community 2010以外は、そのままでは動きません

MEFが、.Net Freameworkにはじめから含まれているのは、.Net 4.0(Visual Studio 2010)だけです。それ以降の環境で利用するためには、Microsoft CompositionをNugetマネージャーを使って取得しておく必要があります。一度、パッケージをインストールすると意識することがないため、「Microsoft Composition」をインストールする必要があることに触れていない情報が多いので、提供されているサンプルが動かない場合は確認してみましょう。

9: Communicating Between Loosely Coupled Components Using the Prism Library 5.0 for WPF(原文)

Microsoft Prism Library 5.0 for WPFの開発者のガイドから

大規模で複雑なWPFアプリケーションを構築するとき、一般的なアプローチは、分離したモジュールアセンブリに機能を分割することです。 また、それは、これらのモジュールの間での、デリゲート・コマンド、領域コンテキスト、共有されたサービスの利用、 そして、イベント・アグリゲータを通して、達成されることができる、静的参照の使用を最小限にすることが、望ましいです。 これは、モジュールが、独立して開発、検証、配布、更新できます。そして、それは、疎く結合した通信を強制します。 このトピックは、デリゲート・コマンドとルーティング・コマンドを使用する時、 そして、イベント・アグリゲータと.NET フレームワーク・イベントを使用するとき、ガイダンスを提供します。

モジュール間の情報をやりとりする時、あなたが、最良の決定をすることができるように、 あなたの個々のシナリオの中で使用するための、アプローチの違いを知っていることは、 重要です。Prism Libraryは、次の通信アプローチを提供します。:

  • ソリューション・コマンド。ユーザーとの対話処理から、即時のアクションが予想されるとき、使用します。
  • 領域コンテキスト。ホスト領域内のホストとViewの間で、コンテキスト情報を提供するために、これを使用します。このアプローチは、DataContextとやや類似していますが、それは、それに依存していません。
  • 共有されたサービス。呼び出し側は、サービス上で、メソッドを呼び出すことができます。それは、メッセージの受け取り側で、イベントを呼び出します。先行するものが、どれも適用できない場合、これを使用します。
  • イベント集約。View Model、プレゼンターやコントローラ間の通信のための、直接、動作-反応の期待がない場合、

ソリューション・コマンド

Solution Commanding

あなたが、コマンドの呼び出し元をクリックするような、ユーザー・ジェスチャーに対応する必要がある場合、(例えば、ボタンやメニュー項目)、 そして、あなたが、ビジネス・ロジックを基づいて、有効するために、呼び出し元を望む場合、コマンドを使用します。

Windows Presentation Foundation (WPF)は、メニュー項目とボタンのような、キーボードフォーカスを持っているビジュアル・ツリーの現在の項目に、 関連付けられるコマンド・ハンドラで、コマンドの呼び出し元を結合するのに役に立つRoutedCommandを提供します。

しかしながら、複合的な筋書きで、コマンド・ハンドラは、多くの場合、ViewModelです。それは、ビジュアル・ツリーで、 関連するどんな要素も持っていないか、フォーカスされた要素でありません。この筋書きに対応するために、Prism Libraryは、 あなたが、デリゲート・メソッドを呼び出すことができる、DelegateCommandを提供します。命令が実行される、 そして、CompositeCommandが、あなたが、複数のコマンドを結合できるとき、 これらのコマンドは、組み込みのRoutedCommandとは異なります。それは、ビジュアル・ツリー上に、 そして、その下に、コマンド実行と処理を割り振ります。 これは、あなたが、ビジュアル・ツリーのこの場所で、コマンドを起動し、そして、それを高いレベルで操作できます。

CompositeCommandは、呼び出し元に結合することができる、ICommandの実装です。 CompositeCommandsは、いくつかの子のコマンドに結合されることができます。; CompositeCommandが、呼び出されるとき、子のコマンドもまた、呼び出されます。

CompositeCommandsは、有効化をサポートしています。CompositeCommandsは、 その接続されているコマンドの各々のCanExecuteChangedイベントに耳を傾けます。 それは、続いて、呼び出し元に知らせるこのイベントを起動します。 呼び出し元は、CompositeCommand上で、CanExecuteを呼び出すことによって、このイベントに反応します。 CompositeCommandは、続いて、各々の子のコマンド上で、CanExecuteを呼び出すことによって、 あらためて、すべてのその子のコマンドの意見を尋ねます。CanExecuteへのどんな呼び出しも、 falseを返すとき、CompositeCommandは、falseを返します。このように、呼び出し元を無効にします。

これは、どのように、あなたを、モジュールを横断する通信で支援しますか? Prism Libraryに基づいたアプリケーションは、広域のCompositeCommandsを持ているかもしれません。 それは、Save、Save AllやCancelのような、モジュールを横断する意味を持つ、シェル内で定義されています。 モジュールは、続いて、これらのグローバルコマンドで、それらのローカル・コマンドを登録することができます。 そして、それらの実行に関与しています。

備考

DelegateCommandとCompositeCommandsは、 Prism.Mvvm NuGetパッケージに配置されているMicrosoft.Practices.Prism.Mvvm名前空間で見つかります。

WPFのルーティング・イベントとルーティング・コマンドについて

About WPF Routed Events and Routed Commands

ルーティングイベントは、一種のイベントです。それは、直接、イベントを購読したオブジェクトだけに知らせる代わりに、 要素ツリー内の複数のリスナー上に、ハンドラを呼び出すことができます。WPFのルーティング・コマンドは、 ビジュアル・ツリー内のUI要素によって、コマンド・メッセージを伝えます。 しかし、ツリーの外側の要素は、フォーカスされた要素や明示的な状態の対象とする要素だけで、 上昇したり、下降したりするため、これらのメッセージを受け取りません。 イベントのためのイベント・データは、ルート内の各々の要素に永続化されるため、ルーティングイベントは、 要素ツリーを介して、情報をやりとりするために使用することができます。1つの要素は、イベント・データで、何かを変更することができます。 そして、その変更は、ルート内で、次の要素が利用できるようになります。 その結果、あなたは、次のシナリオの中の、WPFルーティングイベントを使用する必要があります。: 共通ルートに共通のハンドラを定義したり、独自のカスタムコントロールクラスを定義します。

デリゲート・コマンドを作成する

Creating a Delegate Command

デリゲート・コマンドを作成するために、あなたのViewModelのコンストラクタで、DelegateCommand領域をインスタンス化します。 そして、その次に、ICommandプロパティとして、それを公開します。


// ArticleViewModel.cs
public class ArticleViewModel : BindableBase
{
    private readonly ICommand showArticleListCommand;

    public ArticleViewModel(INewsFeedService newsFeedService,
                            IRegionManager regionManager,
                            IEventAggregator eventAggregator)
    {
        this.showArticleListCommand = new DelegateCommand(this.ShowArticleList);

    }

    public ICommand ShowArticleListCommand 
    {
        get { return this.showArticleListCommand; } 
    }
}

複合コマンドを作成する

Creating a Composite Command

複合コマンドを作成するために、コンストラクタ内で、CompositeCommand領域をインスタンス化し、コマンドを追加します。 そして、その次に、ICommandプロパティとして、それを公開します。

C#


public class MyViewModel : BindableBase
{
    private readonly CompositeCommand saveAllCommand;

    public ArticleViewModel(INewsFeedService newsFeedService,
                            IRegionManager regionManager,
                            IEventAggregator eventAggregator)
    {
        this.saveAllCommand = new CompositeCommand();
        this.saveAllCommand.RegisterCommand(new SaveProductsCommand());
        this.saveAllCommand.RegisterCommand(new SaveOrdersCommand());
    }

    public ICommand SaveAllCommand
    {
        get { return this.saveAllCommand; }
    }
}

グローバルに利用できるコマンドを作成する

Making a Command Globally Available

一般的に、グローバルに利用できるコマンドを作成するために、DelegateCommand、 あるいは、CompositeCommandのインスタンスを作成し、静的クラスによって公開します。

C#


public static class GlobalCommands
{
    public static CompositeCommand MyCompositeCommand = new CompositeCommand();
}

あなたのモジュールで、グローバルに利用できるコマンドに、子のコマンドを関連付けます。

C#


GlobalCommands.MyCompositeCommand.RegisterCommand(command1);
GlobalCommands.MyCompositeCommand.RegisterCommand(command2);

備考

あなたのコードのテスト容易性を向上させるために、 あなたは、グローバルに利用できるコマンドを呼び出すために、プロキシ・クラスを使用する、 そして、あなたのテスト内のプロキシ・クラスのモックを作成することができます。

グローバルに利用できるコマンドに結合する

Binding to a Globally Available Command

次のコード例は、WPFのボタンをコマンドに、どのように、結合するかを示します。

XAML


<Button Name="MyCompositeCommandButton" Command="{x:Static local:GlobalCommands.MyCompositeCommand}">Execute My Composite Command </Button>

備考

他の方法は、Application.Resources項目内のApp.xamlファイルの内側のリソースとして、コマンドを格納することです。 続いて、ビュー内で、それが、そのリソースを設定した後に作成する必要があります。- あなたは、呼び出し元をコマンドに加えるために、 Command="{Binding MyCompositeCommand, Source={StaticResource GlobalCommands}}"を設定することができます。

領域コンテキスト。

Region Context

多くのシナリオがあります。あなたが、Viewの間で、コンテキスト情報を共有したいかもしれない場所、 それは、領域内の領域とViewを格納しています。例えば、ビジネス・エンティティを示す、 あるいは、ビジネス・エンティティのための、追加の詳細情報を表示するためのような、マスターの詳細。 Prism Libraryは、次の図に示すように、領域の内部に読み込まれる、 格納される領域とどんなViewの間で、オブジェクトを共有するために、RegionContextという名前の概念を使用します。

RegionContextを使用する

シナリオに依存して、あなたは、(識別子のような)情報の一部や共有されたModelを共有するために、選択できます。 Viewは、RegionContextを取得することができます。 そして、その次に、変更通知のためにサインアップします。 また、Viewは、RegionContextの値を変更することができます。RegionContextを公開する、そして、利用するいくつかの方法があります。:

  • あなたは、Extensible Application Markup Language (XAML)内の領域に、RegionContextを公開することができます。
  • あなたは、コード内の領域に、RegionContextを公開することができます。
  • あなたは、領域内でViewからRegionContextを利用することができます。

備考

そのViewが、DependencyObjectである場合、Prism Libraryは、 現在、領域内で、Viewから、RegionContextを利用することをサポートするだけです。あなたのViewが、DependencyObjectでない場合、 (例えば、あなたは、WPFの自動データ・テンプレートを使用しています。そして、あなたのViewModelを、直接、領域に追加します。)、 カスタムRegionBehaviorを、前のRegionContextに、あなたのViewオブジェクトに作成することについて考えてみてください。

備考

Data Contextプロパティについて

データ・コンテクストは、要素は、結合のために使用されるデータ・ソースに関する、それらの親の要素から、情報を継承できる概念です。 子要素は、自動的に、それらの親の要素のDataContextを継承します。データは、ビジュアル・ツリーを流れ落ちます。

共有サービス

Shared Services

モジュールを横断する通信のもう1つの方法は、共有サービスを介して行われます。 モジュールが読み込まれるとき、モジュールは、それらのサービスをサービス・ロケーターに加えます。 一般的に、サービスは、一般的なインターフェイス型で、サービス・ロケーターから、登録されて、取得されます。 これは、モジュールに静的参照を必要とすることなく、モジュールが、他のモジュールで提供されるサービスを使用できます。 サービス・インスタンスは、モジュール全体で共有されます。 それで、あなたは、データを共有し、そして、モジュール間でメッセージを渡すことができます。

株式トレーダーのリファレンス実装(株トレーダーRI)では、Marketモジュールは、IMarketFeedServiceの実装を提供します。 Positionモジュールは、サービスの位置と解像度を提供する、シェル・アプリケーションの依存関係注入コンテナを使用することにより、 これらのサービスを利用します。IMarketFeedServiceは、StockTraderRI.Infrastructure共有アセンブリで見つかるように、他のモジュールで利用されることを示します。 しかし、このインターフェイスの具体的な実装は、Marketモジュール内で、直接定義されているように、 共有する必要はありません。そして、他のモジュールと独立して、更新することができます。

C#


// MarketFeedService.cs
[Export(typeof(IMarketFeedService))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MarketFeedService : IMarketFeedService, IDisposable
{
    ...
}

これは、モジュールを横断する通信に役立ちます。サービスの利用者は、サービスを提供しているモジュールに静的参照を必要としていないため、 このサービスは、モジュールの間で、データを送信、あるいは、受信するために使用することができます。

備考

いくつかの依存関係注入コンテナは、この例で示すように、属性を使用して依存関係の登録ができます。 他のコンテナは、明示的な登録を使用するかもしれません。これらの場合では、登録は、Prismが、IModule.Initializeメソッドを呼び出すとき、 一般的に、モジュール読み込みの間に、発生します。詳しくは、モジュール・アプリケーション開発を参照してください。

イベント集約。

Event Aggregation

Prism Libraryは、イベントの仕組みを提供します。 それは、アプリケーションの疎く結合したコンポーネントの間で、通信を有効にします。 この仕組みは、イベント・アグリゲータ・サービスに基づいています。 発行者と購読者が、イベントを通して、情報をやりとりできます。そして、しかし、直接、互いへの参照がありません。

EventAggregatorは、マルチキャストpublish/subscribe機能を提供します。これは、複数の発行者でできることを示しています。 それは、同じイベントを呼び出します。そして、それらは、複数の購読者が、同じイベントを聞き取ることができます。 モジュールを横断してイベントを公開する、そして、コントローラとプレゼンターのような、 ビジネス・ロジック・コード間でメッセージを送信するとき、EventAggregatorを使用することについて考えてみてください。

その一例として、株式のトレーダーから、Process Orderボタンが、クリックされる時、注文がうまく処理されます。; この場合、他のモジュールは、注文がうまく処理されたことを知っている必要があります。それで、それらは、それらのViewを更新することができます。

Prism Libraryで作成されるイベントは、型指定されたイベントです。これは、あなたが、アプリケーションを実行する前に、 あなたが、エラーを発見するために、コンパイル時の型検査を利用できることを示しています。Prismライブラリでは、 EventAggregatorは、特定のEventBaseを配置するために、購読者や発行者を提供します。 また、イベント・アグリゲータは、次の図に示すように、複数の発行者と複数の購読者を認めます。

イベント・アグリゲータ

イベント・アグリゲータ

Event aggregator

備考

.NET フレームワーク・イベントについて

使用する.NET フレームワーク・イベントは、疎結合が、要求されない場合、コンポーネントの間の通信のための、最も簡単でわかりやすい方法です。 .NET Frameworkのイベントは、Publish-Subscribeパターンを実装していますが、オブジェクトを購読します。 あなたは、そのオブジェクトへの直接参照を必要とします。 それは、複合アプリケーションにおいて、一般的に、他のモジュールの中に存在します。 これは、結果として、密接に結合した設計になります。その結果、.NET Framework イベントは、モジュールの間の代わりに、モジュール内での通信のために使用されます。 あなたが、.NET Frameworkイベントを使用する場合、あなたは、メモリリークに、とても注意する必要があります。 特に、あなたが、非静的や短命なコンポーネントを持っている場合、それは、静的、あるいは、より長く生きるイベントを購読します。 あなたが、購読者の登録を取り消さない場合、それは、発行者によって、生きた状態で維持されます。 そして、これは、最初のものが、ガーベージ・コレクトするのを防ぎます。

IEventAggregator

IEventAggregator

EventAggregatorクラスは、コンテナのサービスとして提供されます。そして、IEventAggregatorインターフェイスによって取得することができます。 イベント・アグリゲータは、配置、あるいは、構築イベントのための、そして、システム内で、イベントのコレクションを維持することのための役割を果たします。

C#


public interface IEventAggregator
{        
   TEventType GetEvent<TEventType>() where TEventType : EventBase;
}

EventAggregatorは、それが、すでに構築されていない場合、その最初のアクセスでイベントを構築します。 これは、イベントが利用できるかどうかに関係なく、判断する必要から発行者や購読者を軽減します。

PubSubEvent

発行者と購読者を結合する実際の作業は、PubSubEventクラスによって実行されます。 これは、Prism Libraryに含まれている、EventBaseクラスの唯一の実装です。 このクラスは、購読者のリストを維持し、そして、購読者へのイベントの発送を処理します。

PubSubEventクラスは、ジェネリック・クラスです。それは、ジェネリック型として定義されているペイロード型を必要とします。これは、コンパイル時に、強制するのに役立ちます。 その発行者と購読者は、うまくいくイベント接続のための正しいメソッドを提供します。次に示すコードは、PubSubEventクラスの部分的な定義を示しています。

備考

PubSubEventは、Prism.PubSubEvents NuGetパッケージに配置される、Microsoft.Practices.SubSubEvents名前空間で見つかります。

C#


// PubSubEvent.cs
public class PubSubEvent<TPayload> : EventBase
{
    ...
    public SubscriptionToken Subscribe(Action<TPayload> action);
    public SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption);
    public SubscriptionToken Subscribe(Action<TPayload> action, bool keepSubscriberReferenceAlive)
    public SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive)

    public virtual SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive); 
    public virtual SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<TPayload> filter);
    public virtual void Publish(TPayload payload);
    public virtual void Unsubscribe(Action<TPayload> subscriber); 
    public virtual bool Contains(Action<TPayload> subscriber)
    ...
}

イベントを作成して、公開する

Creating and Publishing Events

次のセクションでは、PubSubEventを作成し、公開し、そして、IEventAggregatorインターフェイスを使用して、購読する方法を説明します。

イベントを作成する

Creating an Event

PubSubEventは、アプリケーションの、あるいは、モジュールの特定のイベントのための基底クラスであることを意図としています。 TPayLoadは、イベントのペイロード型です。ペイロードは、引数です。それは、イベントが、公開されているとき、購読者に渡されるでしょう。

例えば、次のコードは、株トレーダーのリファレンス実装(株トレーダーRI)に、TickerSymbolSelectedEventを表示します。 ペイロードは、会社記号が含まれている文字列です。このクラスが空のための実装をどのように行うかに注意します。

C#


public class TickerSymbolSelectedEvent : PubSubEvent<string>{}

備考

複合アプリケーションでは、イベントは、複数のモジュール間で、頻繁に共有されます。それで、それらは、共通の場所で、定義されます。 株トレーダーRIでは、これは、StockTraderRI.Infrastructureプロジェクトの中で実行します。

イベントを公開する

Publishing an Event

発行者は、EventAggregatorからイベントを取得し、そして、Publishメソッドを呼び出すことで、イベントを発生させます。 EventAggregatorにアクセスするために、あなたは、クラスのコンストラクタへ、IEventAggregator型のパラメータを追加することで、依存関係の注入を使用することができます。

次のコードは、TickerSymbolSelectedEventの発行を説明します。

C#


this.eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Publish("STOCK0");

イベントを購読する

Subscribing to Events

購読者は、PubSubEventクラス上にオーバーロードした利用できるSubscribeメソッドの1つを使用しているイベントに参加することができます。 PubSubEventsを購読するための、いくつかの方法があります。どのオプションが、あなたの必要に最も適切か判断するのを助けるために、次の基準を使用します。:

  • あなたが、イベントを受け取るとき、UI要素を更新できる必要がある場合、UIスレッドで、イベントを受けるために購読します。
  • あなたが、イベントをフィルタリングする必要がある場合、購読するとき、フィルタ・デリゲートを提供します。
  • あなたが、イベントの処理能力に懸念がある場合、強く参照されたデリゲートを使用することについて考えてみてください。 購読するとき、そして、その次に、手動で、PubSubEventの購読を中止します。
  • 前述のいずれも適用しない場合、既定の購読を使用します。

次のセクションでは、これらのオプションを説明します。

UIスレッド上で購読する

Subscribing on the UI Thread

頻繁に、購読者は、イベントに応じて、UI要素を更新する必要があるでしょう。WPFでは、UIスレッドだけは、UI要素を更新することができます。

既定では、購読者は、発行者のスレッド上で、イベントを受け取ります。 発行者が、UIスレッドからイベントを送信する場合、購読者は、UIを更新することができます。 しかしながら、発行者のスレッドが、バックグラウンド・スレッドである場合、購読者は、直接、UI要素を更新できない場合があります。 この場合、購読者は、UIスレッドで、Dispatcherクラスを使用して、更新を予定に入れる必要があります。

Prism Libraryで提供されるPubSubEventは、 購読者が、UIスレッド上で自動的にイベントを受け取ることを提供することによって、支援することができます。 次のコードの例に示すように、購読者は、これを購読の間、示します。

C#


public void Run()
{
   ...
   this.eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Subscribe(ShowNews, ThreadOption.UIThread);
);
}

public void ShowNews(string companySymbol)
{
   this.articlePresentationModel.SetTickerSymbol(companySymbol);
}

次のオプションは、ThreadOptionのために利用できます。:

  • PublisherThread。発行者のスレッド上で、イベントを受けるために、この設定を使用します。これは、既定の設定です。
  • BackgroundThread。.NET Frameworkスレッド-プール・スレッド上で、非同期で、イベントを受信するために、この設定を使用します。
  • UIThread。UIスレッド上で、イベントを受けるために、この設定を使用します。

備考

UIスレッド上で、PubSubEventsを、購読者に公開するため、EventAggregatorは、最初に、UIスレッド上で、構築される必要があります。

購読フィルタリング

Subscription Filtering

購読者は、公開されたイベントのすべてのインスタンスを取り扱う必要はないかもしれません。 これらの場合では、購読者は、フィルタ・パラメータを使用することができます。フィルタ・パラメータは、 イベントが、公開されたイベントのペイロードが、必要となる基準のセットと一致する場合、呼び出された購読者コールバックを持つために、 判断するために発行されるとき、type System.Predicateで、実行されるデリゲートです。 ペイロードが、指定された基準を満たさない場合、購読者コールバックは、実行されません。

頻繁に、このフィルタは、次のコードの例に示すように、ラムダ式として指定されます。

C#


FundAddedEvent fundAddedEvent = this.eventAggregator.GetEvent<FundAddedEvent>();

fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, false,
fundOrder => fundOrder.CustomerId == this.customerId);

備考

Subscribeメソッドは、type Microsoft.Practices.Prism.Events.SubscriptionTokenの購読トークンを返します。 それは、後で、イベントの購読を削除するために使用することができます。コールバック・デリゲートとして、 あなたが、匿名型デリゲート、あるいは、ラムダ式を使用するとき、 あるいは、あなたが、異なるフィルタで、同じイベント・ハンドラを購読するとき、このトークンは、特に役に立ちます。

これは、コールバック・デリゲート内から、ペイロード・オブジェクトを変更することは、推奨されません。 なぜなら、いくつかのスレッドは、同時に、ペイロード・オブジェクトを呼び出すことができます。 あなたは、同時実行エラーを避けるために、ペイロードを不変にすることができます。

強い参照を使用して、購読する

Subscribing Using Strong References

あなたが、短い期間に、複数のイベントを呼び出し、そして、それらの処理能力の懸念に注意する場合、 あなたは、強いデリゲート参照で、購読する必要があるかもしれません。 あなたが、それを行う場合、購読者を取り除くとき、あなたは、続いて、イベントから、手動で、購読を中止する必要があります。

既定では、PubSubEventは、購読の購読者のハンドラとフィルタに、弱いデリゲート参照を保持します。 これは、PubSubEventが保持する参照が、購読者のガーベージ・コレクションを妨げないことを、示しています。 弱いデリゲート参照を使用することは、購読者を、購読を中止する必要性を軽減します。そして、適切なガーベージ・コレクションを提供します。

しかしながら、この弱いデリゲート参照を保持することは、対応する強い参照に比べて、より遅くなります。 ほとんどアプリケーションでは、この処理能力は、顕著ではありませんが、あなたのアプリケーションが、短い期間に 、多数のイベントを発行する場合、あなたは、PubSubEventで、強い参照を使用する必要があるかもしれません。 あなたが、強いデリゲート参照を使用する場合、あなたの購読者は、それが、もはや使用されないとき、 あなたの購読しているオブジェクトの適切なガーベージ・コレクションを有効にするために、購読を中止する必要があります。

強い参照で購読するには、次のコードの例に示すように、Subscribeメソッドで、keepSubscriberReferenceAliveパラメータを使用します。

C#


FundAddedEvent fundAddedEvent = eventAggregator.GetEvent<FundAddedEvent>();

bool keepSubscriberReferenceAlive = true;

fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, keepSubscriberReferenceAlive, fundOrder => fundOrder.CustomerId == _customerId);

keepSubscriberReferenceAliveパラメータは、type boolです。:

  • trueに設定されると、イベント・インスタンスは、購読者インスタンスに強い参照を保有します。 それにより、それが、ガベージコレクションを取得することができません。 どのように、購読を中止するかについては、このトピックの後の、イベントから購読を中止するの項目を参照してください。
  • falseに設定されたとき、(このパラメータを省略したときの既定の値)、イベントは、購読者インスタンスに、弱い参照を保持します。 それによって、それへの他の参照がないとき、購読者インスタンスが、収集されたとき、 ガーベジコレクタが、購読者インスタンスを取り除くことができ、イベントは、自動的に、購読を中止します。
既定の購読

Default Subscriptions

最少限、あるいは、既定の購読のため、購読者は、イベント通知を受け取る適切な署名で、コールバック・メソッドを提供する必要があります。 例えば、次のコードの例に示すように、TickerSymbolSelectedEventのためのハンドラは、文字列パラメータを取得するメソッドを必要とします。

イベントから購読を中止する

Unsubscribing from an Event

あなたの購読者が、イベントを受けることをもはや望まない場合、あなたの購読者のハンドラを使用して、 あなたは、購読を中止することができます。あるいは、あなたは、購読トークンを使用することで、購読を中止することができます。

次のコード例は、どのように、ハンドラに、直接、購読を中止するかを示します。

C#


FundAddedEvent fundAddedEvent = this.eventAggregator.GetEvent<FundAddedEvent>();

fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.PublisherThread);

fundAddedEvent.Unsubscribe(FundAddedEventHandler);

次のコード例は、購読トークンで、どのように、購読を中止するかを示します。トークンは、Subscribeメソッドからの戻り値として、指定されます。


FundAddedEvent fundAddedEvent = this.eventAggregator.GetEvent<FundAddedEvent>();

subscriptionToken = fundAddedEvent.Subscribe(FundAddedEventHandler, ThreadOption.UIThread, false, fundOrder => fundOrder.CustomerId == this.customerId);

fundAddedEvent.Unsubscribe(subscriptionToken);

詳細情報

More Information

弱い参照の詳細については、MSDNの弱い参照を参照してください。

このエントリーをはてなブックマークに追加

Home PC C# Illustration

Copyright (C) 2011 Horio Kazuhiko(kukekko) All Rights Reserved.
kukekko@gmail.com
ご連絡の際は、お問い合わせページのURLの明記をお願いします。
「掲載内容は私自身の見解であり、所属する組織を代表するものではありません。」