如何:实现监视程序
观察程序设计模式要求区分观察程序(注册获取通知)和提供程序(监视数据并将通知发送到一个或多个观察程序)。 本主题介绍了如何创建观察程序。 相关主题如何:实现提供程序中介绍了如何创建提供程序。
创建观察程序的具体步骤
定义观察程序,即实现 System.IObserver<T> 接口的类型。 例如,下面的代码定义了
TemperatureReporter
类型,即使用Temperature
泛型类型参数的构造 System.IObserver<T> 实现。public class TemperatureReporter : IObserver<Temperature>
Public Class TemperatureReporter : Implements IObserver(Of Temperature)
如果观察程序可以在提供程序调用 IObserver<T>.OnCompleted 实现前停止接收通知,请定义专用变量,用于保留提供程序 IObservable<T>.Subscribe 方法返回的 IDisposable 实现。 还应定义订阅方法,用于调用提供程序的 Subscribe 方法,并存储返回的 IDisposable 对象。 例如,下面的代码定义
unsubscriber
专用变量,并定义Subscribe
方法,用于调用提供程序的 Subscribe 方法,并将返回的对象分配给unsubscriber
变量。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 Sub
实现 IObserver<T> 接口定义的三个方法: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 {0}°C at {1:g}", value.Degrees, value.Date); if (first) { last = value; first = false; } else { Console.WriteLine(" Change: {0}° in {1:g}", value.Degrees - last.Degrees, value.Date.ToUniversalTime() - last.Date.ToUniversalTime()); } }
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
示例
下面的示例包含 TemperatureReporter
类的完整源代码,提供了温度监视应用的 IObserver<T> 实现。
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 {0}°C at {1:g}", value.Degrees, value.Date);
if (first)
{
last = value;
first = false;
}
else
{
Console.WriteLine(" Change: {0}° in {1:g}", value.Degrees - last.Degrees,
value.Date.ToUniversalTime() - last.Date.ToUniversalTime());
}
}
}
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