IObserver<T> 接口

定义

提供用于接收基于推送的通知的机制。

C#
public interface IObserver<in T>

类型参数

T

提供通知信息的对象。

这是逆变类型参数。 即,可以使用指定的类型,也可以使用派生程度较低的任何类型。 有关协变和逆变的详细信息,请参阅泛型中的协变和逆变
派生

示例

以下示例演示观察程序设计模式。 它定义一个 Location 包含纬度和经度信息的类。

C#
public struct Location
{
   double lat, lon;

   public Location(double latitude, double longitude)
   {
      this.lat = latitude;
      this.lon = longitude;
   }

   public double Latitude
   { get { return this.lat; } }

   public double Longitude
   { get { return this.lon; } }
}

LocationReporter 类提供 IObserver<T> 实现。 它显示有关控制台当前位置的信息。 它的构造函数包括一个 name 参数,该参数允许 LocationReporter 实例在其字符串输出中标识自身。 它还包括一个 Subscribe 方法,该方法包装对提供程序方法的 Subscribe 调用。 这样,该方法就可以向私有变量分配返回 IDisposable 的引用。 该 LocationReporter 类还包括一个 Unsubscribe 方法,该方法调用 IDisposable.Dispose 该方法 IObservable<T>.Subscribe 返回的对象的方法。 以下代码定义 LocationReporter 类。

C#
using System;

public class LocationReporter : IObserver<Location>
{
   private IDisposable unsubscriber;
   private string instName;

   public LocationReporter(string name)
   {
      this.instName = name;
   }

   public string Name
   {  get{ return this.instName; } }

   public virtual void Subscribe(IObservable<Location> provider)
   {
      if (provider != null)
         unsubscriber = provider.Subscribe(this);
   }

   public virtual void OnCompleted()
   {
      Console.WriteLine("The Location Tracker has completed transmitting data to {0}.", this.Name);
      this.Unsubscribe();
   }

   public virtual void OnError(Exception e)
   {
      Console.WriteLine("{0}: The location cannot be determined.", this.Name);
   }

   public virtual void OnNext(Location value)
   {
      Console.WriteLine("{2}: The current location is {0}, {1}", value.Latitude, value.Longitude, this.Name);
   }

   public virtual void Unsubscribe()
   {
      unsubscriber.Dispose();
   }
}

LocationTracker 类提供 IObservable<T> 实现。 其 TrackLocation 方法传递了一个可为 Location null 的对象,该对象包含纬度和经度数据。 Location如果值不是null,该方法TrackLocation将调用OnNext每个观察程序的方法。

C#
public class LocationTracker : IObservable<Location>
{
   public LocationTracker()
   {
      observers = new List<IObserver<Location>>();
   }

   private List<IObserver<Location>> observers;

   public IDisposable Subscribe(IObserver<Location> observer)
   {
      if (! observers.Contains(observer))
         observers.Add(observer);
      return new Unsubscriber(observers, observer);
   }

   private class Unsubscriber : IDisposable
   {
      private List<IObserver<Location>>_observers;
      private IObserver<Location> _observer;

      public Unsubscriber(List<IObserver<Location>> observers, IObserver<Location> observer)
      {
         this._observers = observers;
         this._observer = observer;
      }

      public void Dispose()
      {
         if (_observer != null && _observers.Contains(_observer))
            _observers.Remove(_observer);
      }
   }

   public void TrackLocation(Nullable<Location> loc)
   {
      foreach (var observer in observers) {
         if (! loc.HasValue)
            observer.OnError(new LocationUnknownException());
         else
            observer.OnNext(loc.Value);
      }
   }

   public void EndTransmission()
   {
      foreach (var observer in observers.ToArray())
         if (observers.Contains(observer))
            observer.OnCompleted();

      observers.Clear();
   }
}

Location如果值为值null,该方法TrackLocation将实例化一个LocationNotFoundException对象,如以下示例所示。 然后,它会调用每个观察程序 OnError 的方法,并传递该 LocationNotFoundException 对象。 请注意, LocationNotFoundException 派生自 Exception 但不添加任何新成员。

C#
public class LocationUnknownException : Exception
{
   internal LocationUnknownException()
   { }
}

观察程序通过调用对象IObservable<T>.Subscribe的方法注册以接收通知TrackLocation,该方法将对观察程序对象的引用分配给专用泛型List<T>对象。 该方法返回一个对象,该对象是一个UnsubscriberIDisposable实现,使观察程序能够停止接收通知。 该 LocationTracker 类还包括一个 EndTransmission 方法。 如果没有其他位置数据可用,该方法将调用每个观察程序的方法,然后清除观察程序 OnCompleted 的内部列表。

然后,以下代码实例化提供程序和观察程序。

C#
using System;

class Program
{
   static void Main(string[] args)
   {
      // Define a provider and two observers.
      LocationTracker provider = new LocationTracker();
      LocationReporter reporter1 = new LocationReporter("FixedGPS");
      reporter1.Subscribe(provider);
      LocationReporter reporter2 = new LocationReporter("MobileGPS");
      reporter2.Subscribe(provider);

      provider.TrackLocation(new Location(47.6456, -122.1312));
      reporter1.Unsubscribe();
      provider.TrackLocation(new Location(47.6677, -122.1199));
      provider.TrackLocation(null);
      provider.EndTransmission();
   }
}
// The example displays output similar to the following:
//      FixedGPS: The current location is 47.6456, -122.1312
//      MobileGPS: The current location is 47.6456, -122.1312
//      MobileGPS: The current location is 47.6677, -122.1199
//      MobileGPS: The location cannot be determined.
//      The Location Tracker has completed transmitting data to MobileGPS.

注解

IObserver<T>IObservable<T>接口为基于推送的通知提供了通用机制,也称为观察程序设计模式。 接口 IObservable<T> 表示 (提供程序) 发送通知的类; IObserver<T> 接口表示 (观察程序) 接收通知的类。 T 表示提供通知信息的类。

IObserver<T>实现通过将自身实例传递给提供程序IObservable<T>.Subscribe的方法,安排从提供程序 (IObservable<T>实现) 接收通知。 此方法返回一个 IDisposable 对象,该对象可用于在提供程序完成发送通知之前取消订阅观察程序。

IObserver<T> 接口定义了观察程序必须实现的以下三种方法:

  • 此方法 OnNext 通常由提供程序调用,以向观察者提供新的数据或状态信息。

  • 提供程序 OnError 通常调用的方法指示数据不可用、无法访问或损坏,或者提供程序遇到其他一些错误情况。

  • 此方法 OnCompleted 通常由提供程序调用,以指示它已完成向观察程序发送通知。

方法

OnCompleted()

通知观察者提供程序已完成发送基于推送的通知。

OnError(Exception)

通知观察者提供程序遇到错误情况。

OnNext(T)

向观察者提供新数据。

适用于

产品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

另请参阅