Procedura: Implementare un elemento Observer
Lo schema progettuale degli observer richiede una divisione tra un observer, che si registra per le notifiche, e un provider, che monitora i dati e invia notifiche a uno o più observer. Questo argomento descrive come creare un observer. Un argomento correlato, Procedura: Implementare un provider, descrive come creare un provider.
Per creare un observer
Definire l'observer, che è un tipo che implementa l'interfaccia System.IObserver<T>. Ad esempio, il codice seguente definisce un tipo denominato
TemperatureReporter
che rappresenta un'implementazione costruita System.IObserver<T> con un argomento di tipo genericoTemperature
.public class TemperatureReporter : IObserver<Temperature>
Public Class TemperatureReporter : Implements IObserver(Of Temperature)
Se l'observer può smettere di ricevere notifiche prima che il provider chiami la relativa implementazione IObserver<T>.OnCompleted, definire una variabile privata che conterrà l'implementazione IDisposable restituita dal metodo IObservable<T>.Subscribe del provider. È anche necessario definire un metodo di sottoscrizione che chiama il metodo Subscribe del provider e archivia l'oggetto IDisposable restituito. Ad esempio, il codice seguente definisce una variabile privata denominata
unsubscriber
e un metodoSubscribe
che chiama il metodo Subscribe del provider e assegna l'oggetto restituito alla variabileunsubscriber
.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
Definire un metodo che consente all'observer di smettere di ricevere interrompere notifiche prima che il provider chiami la relativa implementazione IObserver<T>.OnCompleted, se questa funzionalità è necessaria. L'esempio seguente definisce un metodo
Unsubscribe
.public virtual void Unsubscribe() { unsubscriber.Dispose(); }
Public Overridable Sub Unsubscribe() unsubscriber.Dispose() End Sub
Fornire le implementazioni dei tre metodi definiti dall'interfaccia IObserver<T>: IObserver<T>.OnNext, IObserver<T>.OnError e IObserver<T>.OnCompleted. A seconda del provider e delle esigenze dell'applicazione, i metodi OnError e OnCompleted possono essere implementazioni dello stub. Si noti che il metodo OnError non deve gestire l'oggetto Exception passato come eccezione e che il metodo OnCompleted è libero di chiamare l'implementazione IDisposable.Dispose del provider. L'esempio seguente mostra l'implementazione IObserver<T> della classe
TemperatureReporter
.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
Esempio
L'esempio seguente contiene il codice sorgente completo per la classe TemperatureReporter
, che fornisce l'implementazione IObserver<T> per un'applicazione di monitoraggio della temperatura.
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