IObservable<T> Interface
Definitie
Belangrijk
Bepaalde informatie heeft betrekking op een voorlopige productversie die aanzienlijk kan worden gewijzigd voordat deze wordt uitgebracht. Microsoft biedt geen enkele expliciete of impliciete garanties met betrekking tot de informatie die hier wordt verstrekt.
Hiermee definieert u een provider voor pushmeldingen.
generic <typename T>
public interface class IObservable
public interface IObservable<out T>
type IObservable<'T> = interface
Public Interface IObservable(Of Out T)
Type parameters
- T
Het object dat meldingsinformatie biedt.
Dit type parameter is covariant. U kunt het type dat u hebt opgegeven gebruiken of een type dat meer is afgeleid. Zie Covariantie en Contravariantie in Algemene typen voor meer informatie over covariantie en contravariantie.- Afgeleid
Voorbeelden
In het volgende voorbeeld ziet u het ontwerppatroon van de waarnemer. Hiermee wordt een Location klasse gedefinieerd die informatie over breedtegraad en lengtegraad bevat.
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
De LocationTracker klasse biedt de IObservable<T> implementatie. De TrackLocation methode wordt doorgegeven aan een null-object Location dat de breedte- en lengtegraadgegevens bevat. Als de Location waarde niet nullis, roept de TrackLocation methode de OnNext methode van elke waarnemer aan.
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
Als de Location waarde is null, wordt met de TrackLocation methode een LocationUnknownException object geïnstitueert. Dit wordt weergegeven in het volgende voorbeeld. Vervolgens wordt de methode van OnError elke waarnemer aangeroepen en doorgegeven aan het LocationUnknownException object. Houd er rekening mee dat LocationUnknownException dit is afgeleid van Exception, maar geen nieuwe leden toevoegt.
public class LocationUnknownException : Exception
{
internal LocationUnknownException()
{ }
}
exception LocationUnknownException
Public Class LocationUnknownException : Inherits Exception
Friend Sub New()
End Sub
End Class
Waarnemers registreren zich voor het ontvangen van meldingen van een LocationTracker object door de IObservable<T>.Subscribe methode aan te roepen, waarmee een verwijzing naar het waarnemersobject wordt toegewezen aan een privé-algemeen List<T> object. De methode retourneert een Unsubscriber object, een IDisposable implementatie waarmee waarnemers geen meldingen meer kunnen ontvangen. De LocationTracker klasse bevat ook een EndTransmission methode. Wanneer er geen verdere locatiegegevens beschikbaar zijn, roept de methode de methode van OnCompleted elke waarnemer aan en wist de interne lijst met waarnemers.
In dit voorbeeld biedt de LocationReporter klasse de IObserver<T> implementatie. Er wordt informatie weergegeven over de huidige locatie naar de console. De constructor bevat een name parameter, waarmee het LocationReporter exemplaar zichzelf in de tekenreeksuitvoer kan identificeren. Het bevat ook een Subscribe methode, waarmee een aanroep naar de methode van Subscribe de provider wordt verpakt. Hiermee kan de methode de geretourneerde verwijzing toewijzen aan een privévariabele IDisposable . De LocationReporter klasse bevat ook een Unsubscribe methode die de IDisposable.Dispose methode aanroept van het object dat door de IObservable<T>.Subscribe methode wordt geretourneerd. De volgende code definieert de LocationReporter klasse.
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
Met de volgende code worden de provider en de waarnemer geïnstitueert.
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.
Opmerkingen
De IObserver<T> en IObservable<T> interfaces bieden een gegeneraliseerd mechanisme voor pushmeldingen, ook wel bekend als het ontwerppatroon van de waarnemer. De IObservable<T> interface vertegenwoordigt de klasse die meldingen verzendt (de provider); de IObserver<T> interface vertegenwoordigt de klasse die deze ontvangt (de waarnemer).
T vertegenwoordigt de klasse die de meldingsgegevens levert. In sommige pushmeldingen kan de IObserver<T> implementatie T hetzelfde type vertegenwoordigen.
De provider moet één methode implementeren, Subscribedie aangeeft dat een waarnemer pushmeldingen wil ontvangen. Bellers aan de methode geven een instantie van de waarnemer door. De methode retourneert een IDisposable implementatie waarmee waarnemers meldingen op elk gewenst moment kunnen annuleren voordat de provider deze niet meer verzendt.
Op elk gewenst moment kan een bepaalde provider nul, één of meerdere waarnemers hebben. De provider is verantwoordelijk voor het opslaan van verwijzingen naar waarnemers en zorgt ervoor dat ze geldig zijn voordat ze meldingen verzenden. De IObservable<T> interface maakt geen veronderstellingen over het aantal waarnemers of de volgorde waarin meldingen worden verzonden.
De provider verzendt de volgende drie soorten meldingen naar de waarnemer door methoden aan te roepen IObserver<T> :
De huidige gegevens. De provider kan de IObserver<T>.OnNext methode aanroepen om de waarnemer door te geven aan een
Tobject met actuele gegevens, gewijzigde gegevens of nieuwe gegevens.Een foutvoorwaarde. De provider kan de IObserver<T>.OnError methode aanroepen om de waarnemer te waarschuwen dat er een foutvoorwaarde is opgetreden.
Geen verdere gegevens. De provider kan de methode aanroepen om de waarnemer op de IObserver<T>.OnCompleted hoogte te stellen dat het verzenden van meldingen is voltooid.
Methoden
| Name | Description |
|---|---|
| Subscribe(IObserver<T>) |
Hiermee wordt de provider op de hoogte stelt dat een waarnemer meldingen moet ontvangen. |