如何:实现监视程序

观察程序设计模式要求区分观察程序(注册获取通知)和提供程序(监视数据并将通知发送到一个或多个观察程序)。 本主题介绍了如何创建观察程序。 相关主题如何:实现提供程序中介绍了如何创建提供程序。

创建观察程序的具体步骤

  1. 定义观察程序,即实现 System.IObserver<T> 接口的类型。 例如,下面的代码定义了 TemperatureReporter 类型,即使用 Temperature 泛型类型参数的构造 System.IObserver<T> 实现。

    public class TemperatureReporter : IObserver<Temperature>
    
    Public Class TemperatureReporter : Implements IObserver(Of Temperature)
    
  2. 如果观察程序可以在提供程序调用 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
    
  3. 定义一个方法,以便观察程序可以在提供程序调用 IObserver<T>.OnCompleted 实现前停止接收通知(如果需要此功能的话)。 下面的示例定义了 Unsubscribe 方法。

    public virtual void Unsubscribe()
    {
       unsubscriber.Dispose();
    }
    
    Public Overridable Sub Unsubscribe()
        unsubscriber.Dispose()
    End Sub
    
  4. 实现 IObserver<T> 接口定义的三个方法:IObserver<T>.OnNextIObserver<T>.OnErrorIObserver<T>.OnCompleted。 根据提供程序和应用需求,OnErrorOnCompleted 方法可以是存根实现。 请注意,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

请参阅