IObserver<T> Interfaccia
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Fornisce un meccanismo per la ricezione di notifiche basate su push.
generic <typename T>
public interface class IObserver
public interface IObserver<in T>
type IObserver<'T> = interface
Public Interface IObserver(Of In T)
Parametri di tipo
- T
Oggetto che fornisce informazioni di notifica.
Questo parametro di tipo è controvariante, ovvero puoi usare il tipo specificato o qualsiasi tipo meno derivato. Per altre informazioni sulla covarianza e la controvarianza, vedi Covarianza e controvarianza nei generics.- Derivato
Esempio
Nell'esempio seguente viene illustrato il modello di progettazione dell'osservatore. Definisce una Location
classe che contiene informazioni sulla latitudine e la longitudine.
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
classe fornisce l'implementazione IObserver<T> . Visualizza informazioni sulla posizione corrente nella console. Il costruttore include un name
parametro che consente all'istanza di identificarsi nell'output LocationReporter
della stringa. Include anche un Subscribe
metodo che esegue il wrapping di una chiamata al metodo del Subscribe provider. In questo modo il metodo può assegnare il riferimento restituito IDisposable a una variabile privata. La LocationReporter
classe include anche un Unsubscribe
metodo che chiama il IDisposable.Dispose metodo dell'oggetto restituito dal IObservable<T>.Subscribe metodo . Il codice seguente definisce la LocationReporter
classe .
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
classe fornisce l'implementazione IObservable<T> . Il metodo TrackLocation
viene passato a un oggetto nullable Location
che contiene i dati di latitudine e longitudine. Se il Location
valore non null
è , il TrackLocation
metodo chiama il OnNext metodo di ogni osservatore.
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
Se il Location
valore è null
, il metodo crea un'istanza TrackLocation
di un LocationNotFoundException
oggetto , illustrato nell'esempio seguente. Chiama quindi il metodo di OnError ogni osservatore e lo passa all'oggetto LocationNotFoundException
. Si noti che LocationNotFoundException
deriva da Exception ma non aggiunge nuovi membri.
public class LocationUnknownException : Exception
{
internal LocationUnknownException()
{ }
}
exception LocationUnknownException
Public Class LocationUnknownException : Inherits Exception
Friend Sub New()
End Sub
End Class
Gli osservatori registrano per ricevere notifiche da un TrackLocation
oggetto chiamando il relativo IObservable<T>.Subscribe metodo, che assegna un riferimento all'oggetto osservatore a un oggetto generico privato List<T> . Il metodo restituisce un Unsubscriber
oggetto , che è un'implementazione IDisposable che consente agli osservatori di interrompere la ricezione delle notifiche. La LocationTracker
classe include anche un EndTransmission
metodo . Quando non sono disponibili ulteriori dati sulla posizione, il metodo chiama il metodo di OnCompleted ogni osservatore e quindi cancella l'elenco interno di osservatori.
Il codice seguente crea quindi un'istanza del provider e dell'osservatore.
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.
Commenti
Le IObserver<T> interfacce e IObservable<T> forniscono un meccanismo generalizzato per la notifica basata su push, noto anche come modello di progettazione osservatore. L'interfaccia IObservable<T> rappresenta la classe che invia notifiche (il provider); l'interfaccia IObserver<T> rappresenta la classe che li riceve (l'osservatore). T
rappresenta la classe che fornisce le informazioni di notifica.
Un'implementazione IObserver<T> dispone di ricevere notifiche da un provider (un'implementazione IObservable<T> ) passando un'istanza di se stessa al metodo del IObservable<T>.Subscribe provider. Questo metodo restituisce un IDisposable oggetto che può essere utilizzato per annullare la sottoscrizione dell'osservatore prima che il provider finisca l'invio di notifiche.
L'interfaccia IObserver<T> definisce i tre metodi seguenti che l'osservatore deve implementare:
Il OnNext metodo, in genere chiamato dal provider per fornire all'osservatore nuove informazioni sui dati o sullo stato.
Il OnError metodo, che viene in genere chiamato dal provider per indicare che i dati non sono disponibili, inaccessibili o danneggiati o che il provider ha riscontrato un'altra condizione di errore.
Il OnCompleted metodo, che viene in genere chiamato dal provider per indicare che ha completato l'invio di notifiche agli osservatori.
Metodi
OnCompleted() |
Notifica all'osservatore che il provider ha terminato di inviare notifiche basate su push. |
OnError(Exception) |
Notifica all'osservatore una condizione di errore del provider. |
OnNext(T) |
Fornisce nuovi dati all'osservatore. |