.NET では、オブザーバー デザイン パターンはインターフェイスのセットとして実装されます。 System.IObservable<T> インターフェイスはデータ プロバイダーを表します。これは、オブザーバーが通知のサブスクライブを解除できるようにするIDisposable実装を提供する役割も担います。 System.IObserver<T> インターフェイスはオブザーバーを表します。 このトピックでは、これらのインターフェイスを使用してオブザーバー デザイン パターンを実装するときに開発者が従う必要があるベスト プラクティスについて説明します。
スレッド
通常、プロバイダーは、コレクション オブジェクトによって表されるサブスクライバー リストに特定のオブザーバーを追加することによって、 IObservable<T>.Subscribe メソッドを実装し、サブスクライバー リストから特定のオブザーバーを削除することによって IDisposable.Dispose メソッドを実装します。 オブザーバーは、いつでもこれらのメソッドを呼び出すことができます。 さらに、プロバイダー/オブザーバー コントラクトでは、 IObserver<T>.OnCompleted コールバック メソッドの後にサブスクライブ解除を担当するユーザーが指定されていないため、プロバイダーとオブザーバーの両方がリストから同じメンバーを削除しようとする可能性があります。 このような可能性があるため、 Subscribe メソッドと Dispose メソッドの両方がスレッド セーフである必要があります。 通常、これには 同時実行コレクション またはロックの使用が含まれます。 スレッド セーフではない実装では、そうでないことを明示的に文書化する必要があります。
追加の保証は、プロバイダー/オブザーバー コントラクトの上のレイヤーで指定する必要があります。 実装者は、オブザーバー コントラクトに関するユーザーの混乱を避けるために追加の要件を課すときに、明確に呼び出す必要があります。
例外の処理
データ プロバイダーとオブザーバーの間の疎結合のため、オブザーバー デザイン パターンの例外は情報提供を目的としています。 これは、プロバイダーとオブザーバーがオブザーバー デザイン パターンの例外を処理する方法に影響します。
プロバイダー - OnError メソッドの呼び出し
OnErrorメソッドは、IObserver<T>.OnNext メソッドと同様に、オブザーバーへの情報メッセージとして意図されています。 ただし、 OnNext メソッドは、現在または更新されたデータをオブザーバーに提供するように設計されていますが、 OnError メソッドは、プロバイダーが有効なデータを提供できないことを示すように設計されています。
プロバイダーは、例外を処理し、 OnError メソッドを呼び出すときに、次のベスト プラクティスに従う必要があります。
特定の要件がある場合、プロバイダーは独自の例外を処理する必要があります。
プロバイダーは、オブザーバーが特定の方法で例外を処理することを想定したり、要求したりしないでください。
プロバイダーは、更新プログラムを提供する機能を損なう例外を処理するときに、 OnError メソッドを呼び出す必要があります。 このような例外に関する情報は、オブザーバーに渡すことができます。 それ以外の場合は、オブザーバーに例外を通知する必要はありません。
プロバイダーが OnError メソッドまたは IObserver<T>.OnCompleted メソッドを呼び出すと、それ以上通知が表示されなくなり、プロバイダーはオブザーバーの登録を解除できます。 ただし、オブザーバーは、 OnError または IObserver<T>.OnCompleted 通知を受信する前と後の両方を含め、いつでもサブスクリプションを解除することもできます。 オブザーバーの設計パターンでは、プロバイダーまたはオブザーバーがサブスクライブ解除を担当するかどうかは決まります。そのため、両方とも登録解除を試みる可能性があります。 通常、オブザーバーがサブスクリプションを解除すると、サブスクライバー コレクションから削除されます。 シングル スレッド アプリケーションでは、 IDisposable.Dispose 実装では、オブジェクト参照が有効であること、およびオブジェクトがサブスクライバー コレクションのメンバーであることを確認してから削除する必要があります。 マルチスレッド アプリケーションでは、 System.Collections.Concurrent.BlockingCollection<T> オブジェクトなどのスレッド セーフなコレクション オブジェクトを使用する必要があります。
オブザーバー - OnError メソッドの実装
オブザーバーがプロバイダーからエラー通知を受信した場合、オブザーバーは例外を情報として扱う必要があり、特定のアクションを実行する必要はありません。
オブザーバーは、プロバイダーからの OnError メソッド呼び出しに応答するときに、次のベスト プラクティスに従う必要があります。
オブザーバーは、 OnNext や OnErrorなどのインターフェイス実装から例外をスローしないでください。 ただし、オブザーバーが例外をスローする場合は、これらの例外がハンドルされないと想定する必要があります。
呼び出し履歴を保持するには、OnError メソッドに渡されたException オブジェクトをスローするオブザーバーは、例外をスローする前にラップする必要があります。 この目的には、標準の例外オブジェクトを使用する必要があります。
その他のベスト プラクティス
IObservable<T>.Subscribe メソッドで登録を解除しようとすると、null 参照が発生する可能性があります。 そのため、この方法は避けてください。
オブザーバーを複数のプロバイダーにアタッチすることはできますが、推奨されるパターンは、 IObserver<T> インスタンスを 1 つの IObservable<T> インスタンスにのみアタッチすることです。
こちらも参照ください
.NET