Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wzorzec projektowy obserwatora wymaga podziału między obserwatorem, który rejestruje się w celu otrzymywania powiadomień, a dostawcą, który monitoruje dane i wysyła powiadomienia do co najmniej jednego obserwatora. W tym artykule omówiono sposób tworzenia obserwatora. Powiązany artykuł How to implement a provider (Jak zaimplementować dostawcę) omawia sposób tworzenia dostawcy.
Tworzenie obserwatora
Aby utworzyć obserwatora, zaimplementuj System.IObserver<T> interfejs. W poniższych krokach opisano każdy element członkowski, który należy zdefiniować.
Zdefiniuj typ obserwatora System.IObserver<T> , który implementuje interfejs.
Poniższy kod definiuje typ o nazwie
TemperatureReporter, który jest skonstruowaną implementacją System.IObserver<T> z argumentem typu ogólnegoTemperature.namespace TemperatureSample; public sealed class TemperatureReporter : IObserver<Temperature>Namespace Global.TemperatureSample Public NotInheritable Class TemperatureReporter Implements IObserver(Of Temperature)Jeśli obserwator musi anulować subskrypcję przed wywołaniami IObserver<T>.OnCompleteddostawcy , zdefiniuj zmienną prywatną do przechowywania IDisposable zwracanego przez IObservable<T>.Subscribeprogram i zdefiniuj metodę subskrypcji.
Zmienna
unsubscriberprywatna przechowuje IDisposable obiekt. MetodaSubscribewywołuje metodę dostawcy Subscribe i przypisuje zwrócony obiekt dounsubscribermetody .namespace TemperatureSample; public sealed class TemperatureReporter : IObserver<Temperature> { private IDisposable? _unsubscriber; private Temperature? _last; public void Subscribe(IObservable<Temperature> provider) { ArgumentNullException.ThrowIfNull(provider); _unsubscriber = provider.Subscribe(this); }Namespace Global.TemperatureSample Public NotInheritable Class TemperatureReporter Implements IObserver(Of Temperature) Private _unsubscriber As IDisposable Private _last As Temperature? Public Sub Subscribe(provider As IObservable(Of Temperature)) ArgumentNullException.ThrowIfNull(provider) _unsubscriber = provider.Subscribe(Me) End SubZdefiniuj metodę
Unsubscribe, która umożliwia obserwatorowi zatrzymanie odbierania powiadomień przed wywołaniem IObserver<T>.OnCompletedprzez dostawcę .public void Unsubscribe() => _unsubscriber?.Dispose();Public Sub Unsubscribe() _unsubscriber?.Dispose() End SubZaimplementuj trzy metody zdefiniowane przez IObserver<T>: IObserver<T>.OnNext, IObserver<T>.OnErrori IObserver<T>.OnCompleted.
Metody OnError i OnCompleted mogą być implementacjami szkieletowymi. Metoda OnError nie powinna traktować przekazanego Exception jako wyjątku, a OnCompleted może wywołać implementację IDisposable.Dispose dostawcy.
public void OnCompleted() => Console.WriteLine("Additional temperature data won't be transmitted."); // OnError is informational; observers shouldn't treat it as an exception to handle. public void OnError(Exception error) { } public void OnNext(Temperature value) { Console.WriteLine($"The temperature is {value.Degrees}°C at {value.Date:g}"); if (_last is Temperature previous) { TimeSpan elapsed = value.Date.ToUniversalTime() - previous.Date.ToUniversalTime(); Console.WriteLine($" Change: {value.Degrees - previous.Degrees}° in {elapsed:g}"); } _last = value; }Public Sub OnCompleted() Implements IObserver(Of Temperature).OnCompleted Console.WriteLine("Additional temperature data won't be transmitted.") End Sub ' OnError is informational; observers shouldn't treat it as an exception to handle. Public Sub OnError(error_ As Exception) Implements IObserver(Of Temperature).OnError End Sub Public Sub OnNext(value As Temperature) Implements IObserver(Of Temperature).OnNext Console.WriteLine($"The temperature is {value.Degrees}°C at {value.Date:g}") If _last.HasValue Then Dim previous = _last.Value Dim elapsed = value.Date.ToUniversalTime() - previous.Date.ToUniversalTime() Console.WriteLine($" Change: {value.Degrees - previous.Degrees}° in {elapsed:g}") End If _last = value End Sub
Kompletny przykład
W poniższym przykładzie przedstawiono kompletny kod źródłowy klasy TemperatureReporter , który zapewnia implementację IObserver<T> aplikacji do monitorowania temperatury.
namespace TemperatureSample;
public sealed class TemperatureReporter : IObserver<Temperature>
{
private IDisposable? _unsubscriber;
private Temperature? _last;
public void Subscribe(IObservable<Temperature> provider)
{
ArgumentNullException.ThrowIfNull(provider);
_unsubscriber = provider.Subscribe(this);
}
public void Unsubscribe() => _unsubscriber?.Dispose();
public void OnCompleted() =>
Console.WriteLine("Additional temperature data won't be transmitted.");
// OnError is informational; observers shouldn't treat it as an exception to handle.
public void OnError(Exception error) { }
public void OnNext(Temperature value)
{
Console.WriteLine($"The temperature is {value.Degrees}°C at {value.Date:g}");
if (_last is Temperature previous)
{
TimeSpan elapsed = value.Date.ToUniversalTime() - previous.Date.ToUniversalTime();
Console.WriteLine($" Change: {value.Degrees - previous.Degrees}° in {elapsed:g}");
}
_last = value;
}
}
Namespace Global.TemperatureSample
Public NotInheritable Class TemperatureReporter
Implements IObserver(Of Temperature)
Private _unsubscriber As IDisposable
Private _last As Temperature?
Public Sub Subscribe(provider As IObservable(Of Temperature))
ArgumentNullException.ThrowIfNull(provider)
_unsubscriber = provider.Subscribe(Me)
End Sub
Public Sub Unsubscribe()
_unsubscriber?.Dispose()
End Sub
Public Sub OnCompleted() Implements IObserver(Of Temperature).OnCompleted
Console.WriteLine("Additional temperature data won't be transmitted.")
End Sub
' OnError is informational; observers shouldn't treat it as an exception to handle.
Public Sub OnError(error_ As Exception) Implements IObserver(Of Temperature).OnError
End Sub
Public Sub OnNext(value As Temperature) Implements IObserver(Of Temperature).OnNext
Console.WriteLine($"The temperature is {value.Degrees}°C at {value.Date:g}")
If _last.HasValue Then
Dim previous = _last.Value
Dim elapsed = value.Date.ToUniversalTime() - previous.Date.ToUniversalTime()
Console.WriteLine($" Change: {value.Degrees - previous.Degrees}° in {elapsed:g}")
End If
_last = value
End Sub
End Class
End Namespace