IObserver<T> Interfaz
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Proporciona un mecanismo para recibir notificaciones basadas en inserción.
generic <typename T>
public interface class IObserver
public interface IObserver<in T>
type IObserver<'T> = interface
Public Interface IObserver(Of In T)
Parámetros de tipo
- T
Objeto que proporciona información de notificación.
Este parámetro de tipo es contravariante, es decir, puede usar el tipo que haya especificado o cualquier tipo menos derivado. Si desea obtener más información sobre la covarianza y la contravarianza, consulte Covarianza y contravarianza en genéricos.- Derivado
Ejemplos
En el ejemplo siguiente se muestra el patrón de diseño de observador. Define una Location
clase que contiene información de latitud y longitud.
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; } }
}
[<Struct>]
type Location =
{ Latitude: double
Longitude: double }
Public Structure Location
Dim lat, lon As Double
Public Sub New(ByVal latitude As Double, ByVal longitude As Double)
Me.lat = latitude
Me.lon = longitude
End Sub
Public ReadOnly Property Latitude As Double
Get
Return Me.lat
End Get
End Property
Public ReadOnly Property Longitude As Double
Get
Return Me.lon
End Get
End Property
End Structure
La LocationReporter
clase proporciona la IObserver<T> implementación. Muestra información sobre la ubicación actual en la consola. Su constructor incluye un name
parámetro , que permite a la LocationReporter
instancia identificarse en su salida de cadena. También incluye un Subscribe
método , que encapsula una llamada al método del Subscribe proveedor. Esto permite al método asignar la referencia devuelta IDisposable a una variable privada. La LocationReporter
clase también incluye un Unsubscribe
método , que llama al IDisposable.Dispose método del objeto devuelto por el IObservable<T>.Subscribe método . El código siguiente define la LocationReporter
clase .
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();
}
}
open System
type LocationReporter(name) =
let mutable unsubscriber = Unchecked.defaultof<IDisposable>
member _.Name = name
member this.Subscribe(provider: IObservable<Location>) =
if provider <> null then
unsubscriber <- provider.Subscribe this
member _.Unsubscribe() =
unsubscriber.Dispose()
interface IObserver<Location> with
member this.OnCompleted() =
printfn $"The Location Tracker has completed transmitting data to {name}."
this.Unsubscribe()
member _.OnError(_) =
printfn $"{name}: The location cannot be determined."
member _.OnNext(value) =
printfn $"{name}: The current location is {value.Latitude}, {value.Longitude}"
Public Class LocationReporter : Implements IObserver(Of Location)
Dim unsubscriber As IDisposable
Dim instName As String
Public Sub New(ByVal name As String)
Me.instName = name
End Sub
Public ReadOnly Property Name As String
Get
Return instName
End Get
End Property
Public Overridable Sub Subscribe(ByVal provider As IObservable(Of Location))
If provider Is Nothing Then Exit Sub
unsubscriber = provider.Subscribe(Me)
End Sub
Public Overridable Sub OnCompleted() Implements System.IObserver(Of Location).OnCompleted
Console.WriteLine("The Location Tracker has completed transmitting data to {0}.", Me.Name)
Me.Unsubscribe()
End Sub
Public Overridable Sub OnError(ByVal e As System.Exception) Implements System.IObserver(Of Location).OnError
Console.WriteLine("{0}: The location cannot be determined.", Me.Name)
End Sub
Public Overridable Sub OnNext(ByVal value As Location) Implements System.IObserver(Of Location).OnNext
Console.WriteLine("{2}: The current location is {0}, {1}", value.Latitude, value.Longitude, Me.Name)
End Sub
Public Overridable Sub Unsubscribe()
unsubscriber.Dispose()
End Sub
End Class
La LocationTracker
clase proporciona la IObservable<T> implementación. Su TrackLocation
método se pasa a un objeto que acepta Location
valores NULL que contiene los datos de latitud y longitud. Si el Location
valor no null
es , el TrackLocation
método llama al OnNext método de cada observador.
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();
}
}
type Unsubscriber(observers: ResizeArray<IObserver<Location>>, observer: IObserver<Location>) =
interface IDisposable with
member _.Dispose() =
if observer <> null && observers.Contains observer then
observers.Remove observer |> ignore
type LocationTracker() =
let observers = ResizeArray<IObserver<Location>>()
interface IObservable<Location> with
member _.Subscribe(observer) =
if observers.Contains observer |> not then
observers.Add observer
new Unsubscriber(observers, observer)
member _.TrackLocation(loc: Nullable<Location>) =
for observer in observers do
if not loc.HasValue then
observer.OnError LocationUnknownException
else
observer.OnNext loc.Value
member _.EndTransmission() =
for observer in observers.ToArray() do
if observers.Contains observer then
observer.OnCompleted()
observers.Clear()
Public Class LocationTracker : Implements IObservable(Of Location)
Public Sub New()
observers = New List(Of IObserver(Of Location))
End Sub
Private observers As List(Of IObserver(Of Location))
Public Function Subscribe(ByVal observer As System.IObserver(Of Location)) As System.IDisposable _
Implements System.IObservable(Of Location).Subscribe
If Not observers.Contains(observer) Then
observers.Add(observer)
End If
Return New Unsubscriber(observers, observer)
End Function
Private Class Unsubscriber : Implements IDisposable
Private _observers As List(Of IObserver(Of Location))
Private _observer As IObserver(Of Location)
Public Sub New(ByVal observers As List(Of IObserver(Of Location)), ByVal observer As IObserver(Of Location))
Me._observers = observers
Me._observer = observer
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
If _observer IsNot Nothing AndAlso _observers.Contains(_observer) Then
_observers.Remove(_observer)
End If
End Sub
End Class
Public Sub TrackLocation(ByVal loc As Nullable(Of Location))
For Each observer In observers
If Not loc.HasValue Then
observer.OnError(New LocationUnknownException())
Else
observer.OnNext(loc.Value)
End If
Next
End Sub
Public Sub EndTransmission()
For Each observer In observers.ToArray()
If observers.Contains(observer) Then observer.OnCompleted()
Next
observers.Clear()
End Sub
End Class
Si el Location
valor es null
, el TrackLocation
método crea una instancia de un LocationNotFoundException
objeto , que se muestra en el ejemplo siguiente. A continuación, llama al método de OnError cada observador y lo pasa al LocationNotFoundException
objeto . Tenga en cuenta que LocationNotFoundException
se deriva de Exception pero no agrega ningún miembro nuevo.
public class LocationUnknownException : Exception
{
internal LocationUnknownException()
{ }
}
exception LocationUnknownException
Public Class LocationUnknownException : Inherits Exception
Friend Sub New()
End Sub
End Class
Los observadores se registran para recibir notificaciones de un TrackLocation
objeto llamando a su IObservable<T>.Subscribe método , que asigna una referencia al objeto observer a un objeto genérico List<T> privado. El método devuelve un Unsubscriber
objeto , que es una IDisposable implementación que permite a los observadores dejar de recibir notificaciones. La LocationTracker
clase también incluye un EndTransmission
método . Cuando no hay más datos de ubicación disponibles, el método llama al método de OnCompleted cada observador y, a continuación, borra la lista interna de observadores.
A continuación, el código siguiente crea una instancia del proveedor y del observador.
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.
open System
// Define a provider and two observers.
let provider = LocationTracker()
let reporter1 = LocationReporter "FixedGPS"
reporter1.Subscribe provider
let reporter2 = LocationReporter "MobileGPS"
reporter2.Subscribe provider
provider.TrackLocation { Latitude = 47.6456; Longitude = -122.1312 }
reporter1.Unsubscribe()
provider.TrackLocation { Latitude = 47.6677; Longitude = -122.1199 }
provider.TrackLocation(Nullable())
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.
Module Module1
Dim provider As LocationTracker
Sub Main()
' Define a provider and two observers.
provider = New LocationTracker()
Dim reporter1 As New LocationReporter("FixedGPS")
reporter1.Subscribe(provider)
Dim reporter2 As 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(Nothing)
provider.EndTransmission()
End Sub
End Module
' 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.
Comentarios
Las IObserver<T> interfaces y IObservable<T> proporcionan un mecanismo generalizado para la notificación basada en inserción, también conocido como patrón de diseño de observador. La IObservable<T> interfaz representa la clase que envía notificaciones (el proveedor); la IObserver<T> interfaz representa la clase que las recibe (el observador). T
representa la clase que proporciona la información de notificación.
Una IObserver<T> implementación se organiza para recibir notificaciones de un proveedor (una IObservable<T> implementación) pasando una instancia de sí misma al método del IObservable<T>.Subscribe proveedor. Este método devuelve un IDisposable objeto que se puede usar para cancelar la suscripción del observador antes de que el proveedor termine de enviar notificaciones.
La IObserver<T> interfaz define los tres métodos siguientes que el observador debe implementar:
El OnNext método, al que normalmente llama el proveedor para proporcionar al observador información de nuevos datos o estado.
El OnError método, al que normalmente llama el proveedor para indicar que los datos no están disponibles, inaccesibles o dañados, o que el proveedor ha experimentado alguna otra condición de error.
El OnCompleted método, al que normalmente llama el proveedor para indicar que ha terminado de enviar notificaciones a observadores.
Métodos
OnCompleted() |
Informa al observador de que el proveedor ha terminado de enviar notificaciones basadas en inserción. |
OnError(Exception) |
Notifica al observador que el proveedor experimentó una condición de error. |
OnNext(T) |
Proporciona el observador con nuevos datos. |