オブザーバーの設計パターンでは、通知を登録するオブザーバーと、データを監視して 1 つ以上のオブザーバーに通知を送信するプロバイダーとの間の分割が必要です。 このトピックでは、オブザーバーを作成する方法について説明します。 関連トピック「 方法: プロバイダーを実装する」では、プロバイダーを作成する方法について説明します。
オブザーバーを作成するには
オブザーバーを定義します。これは、 System.IObserver<T> インターフェイスを実装する型です。 たとえば、次のコードでは、
Temperatureのジェネリック型引数を使用して構築されたSystem.IObserver<T>実装であるTemperatureReporterという名前の型を定義します。public class TemperatureReporter : IObserver<Temperature>Public Class TemperatureReporter : Implements IObserver(Of Temperature)プロバイダーがIObserver<T>.OnCompleted実装を呼び出す前にオブザーバーが通知の受信を停止できる場合は、プロバイダーの IObservable<T>.Subscribe メソッドによって返されるIDisposable実装を保持するプライベート変数を定義します。 プロバイダーの Subscribe メソッドを呼び出し、返された IDisposable オブジェクトを格納するサブスクリプション メソッドも定義する必要があります。 たとえば、次のコードでは、
unsubscriberという名前のプライベート変数を定義し、プロバイダーのSubscribe メソッドを呼び出し、返されたオブジェクトをunsubscriber変数に割り当てるSubscribeメソッドを定義します。public class TemperatureReporter : IObserver<Temperature> { private IDisposable unsubscriber; private bool first = true; private Temperature last; public virtual void Subscribe(IObservable<Temperature> provider) { unsubscriber = provider.Subscribe(this); }Public Class TemperatureReporter : Implements IObserver(Of Temperature) Private unsubscriber As IDisposable Private first As Boolean = True Private last As Temperature Public Overridable Sub Subscribe(ByVal provider As IObservable(Of Temperature)) unsubscriber = provider.Subscribe(Me) End Subこの機能が必要な場合、プロバイダーがその IObserver<T>.OnCompleted 実装を呼び出す前に、オブザーバーが通知の受信を停止できるようにするメソッドを定義します。 次の例では、
Unsubscribeメソッドを定義します。public virtual void Unsubscribe() { unsubscriber.Dispose(); }Public Overridable Sub Unsubscribe() unsubscriber.Dispose() End SubIObserver<T> インターフェイスで定義されている 3 つのメソッド (IObserver<T>.OnNext、IObserver<T>.OnError、IObserver<T>.OnCompleted) の実装を提供します。 プロバイダーとアプリケーションのニーズに応じて、 OnError メソッドと OnCompleted メソッドをスタブ実装にすることができます。 OnError メソッドは、渡されたException オブジェクトを例外として処理しないでください。また、OnCompleted メソッドはプロバイダーのIDisposable.Dispose実装を自由に呼び出すことができます。 次の例は、
TemperatureReporterクラスのIObserver<T>実装を示しています。public virtual void OnCompleted() { Console.WriteLine("Additional temperature data will not be transmitted."); } public virtual void OnError(Exception error) { // Do nothing. } public virtual void OnNext(Temperature value) { Console.WriteLine($"The temperature is {value.Degrees}°C at {value.Date:g}"); if (first) { last = value; first = false; } else { Console.WriteLine($" Change: {value.Degrees - last.Degrees}° in {value.Date.ToUniversalTime() - last.Date.ToUniversalTime():g}"); } }Public Overridable Sub OnCompleted() Implements System.IObserver(Of Temperature).OnCompleted Console.WriteLine("Additional temperature data will not be transmitted.") End Sub Public Overridable Sub OnError(ByVal [error] As System.Exception) Implements System.IObserver(Of Temperature).OnError ' Do nothing. End Sub Public Overridable Sub OnNext(ByVal value As Temperature) Implements System.IObserver(Of Temperature).OnNext Console.WriteLine("The temperature is {0}°C at {1:g}", value.Degrees, value.Date) If first Then last = value first = False Else Console.WriteLine(" Change: {0}° in {1:g}", value.Degrees - last.Degrees, value.Date.ToUniversalTime - last.Date.ToUniversalTime) End If End Sub
例
次の例には、温度監視アプリケーションのIObserver<T>実装を提供する、TemperatureReporter クラスの完全なソース コードが含まれています。
public class TemperatureReporter : IObserver<Temperature>
{
private IDisposable unsubscriber;
private bool first = true;
private Temperature last;
public virtual void Subscribe(IObservable<Temperature> provider)
{
unsubscriber = provider.Subscribe(this);
}
public virtual void Unsubscribe()
{
unsubscriber.Dispose();
}
public virtual void OnCompleted()
{
Console.WriteLine("Additional temperature data will not be transmitted.");
}
public virtual void OnError(Exception error)
{
// Do nothing.
}
public virtual void OnNext(Temperature value)
{
Console.WriteLine($"The temperature is {value.Degrees}°C at {value.Date:g}");
if (first)
{
last = value;
first = false;
}
else
{
Console.WriteLine($" Change: {value.Degrees - last.Degrees}° in {value.Date.ToUniversalTime() - last.Date.ToUniversalTime():g}");
}
}
}
Public Class TemperatureReporter : Implements IObserver(Of Temperature)
Private unsubscriber As IDisposable
Private first As Boolean = True
Private last As Temperature
Public Overridable Sub Subscribe(ByVal provider As IObservable(Of Temperature))
unsubscriber = provider.Subscribe(Me)
End Sub
Public Overridable Sub Unsubscribe()
unsubscriber.Dispose()
End Sub
Public Overridable Sub OnCompleted() Implements System.IObserver(Of Temperature).OnCompleted
Console.WriteLine("Additional temperature data will not be transmitted.")
End Sub
Public Overridable Sub OnError(ByVal [error] As System.Exception) Implements System.IObserver(Of Temperature).OnError
' Do nothing.
End Sub
Public Overridable Sub OnNext(ByVal value As Temperature) Implements System.IObserver(Of Temperature).OnNext
Console.WriteLine("The temperature is {0}°C at {1:g}", value.Degrees, value.Date)
If first Then
last = value
first = False
Else
Console.WriteLine(" Change: {0}° in {1:g}", value.Degrees - last.Degrees,
value.Date.ToUniversalTime - last.Date.ToUniversalTime)
End If
End Sub
End Class
こちらもご覧ください
.NET