Empfohlene Vorgehensweisen für Beobachterentwurfsmuster
In .NET wird das Beobachterentwurfsmuster als eine Reihe von Schnittstellen implementiert. Die System.IObservable<T>-Schnittstelle stellt den Datenanbieter dar, der auch für die Bereitstellung einer IDisposable-Implementierung verantwortlich ist, mit der Beobachter Benachrichtigungsabonnements kündigen können. Die System.IObserver<T>-Schnittstelle stellt den Beobachter dar. Dieses Thema beschreibt die empfohlenen Vorgehensweisen, die Entwickler befolgen sollten, wenn sie das Beobachterentwurfsmuster unter Verwendung dieser Schnittstellen implementieren.
Threading
In der Regel implementiert ein Anbieter die IObservable<T>.Subscribe-Methode, indem er einen bestimmten Beobachter einer Abonnentenliste hinzufügt, die durch ein Auflistungsobjekt dargestellt wird, und implementiert die IDisposable.Dispose-Methode, indem ein bestimmten Beobachter aus der Abonnentenliste entfernt wird. Ein Beobachter kann diese Methoden jederzeit aufrufen. Da der Anbieter/Beobachter-Vertrag außerdem nicht angibt, wer für das Kündigen nach der IObserver<T>.OnCompleted-Callbackmethode verantwortlich ist, können der Anbieter und der Beobachter beide versuchen, denselben Member aus der Liste zu entfernen. Aufgrund dieser Möglichkeit sollten die Subscribe- und die Dispose-Methode threadsicher sein. In der Regel umfasst dies die Verwendung einer gleichzeitigen Auflistung oder eine Sperre. Für Implementierungen, die nicht threadsicher sind, sollte dies explizit dokumentiert werden.
Alle weiteren Garantien müssen in einer Ebene über dem Anbieter/Beobachter-Vertrag angegeben werden. Implementierer sollten klar kommunizieren, wenn sie zusätzliche Anforderungen auferlegen, um Verwirrungen der Benutzer zum Beobachtervertrag zu vermeiden.
Behandeln von Ausnahmen
Aufgrund der losen Kopplung zwischen einem Datenanbieter und einem Beobachter sollen Ausnahmen im Beobachterentwurfsmuster nur der Information dienen. Dies beeinflusst das Verarbeiten von Ausnahmen im Beobachterentwurfsmuster durch Anbieter und Beobachter.
Der Anbieter – Aufrufen der OnError-Methode
Die OnError-Methode dient als Informationsmeldung an Beobachter – ähnlich wie die IObserver<T>.OnNext-Methode. Allerdings wurde die OnNext-Methode entwickelt, um einem Beobachter aktuelle bzw. aktualisierte Daten bereitzustellen, während die OnError-Methode entwickelt wurde, um anzugeben, dass der Anbieter keine gültige Daten bereitstellen kann.
Der Anbieter sollte diese empfohlenen Vorgehensweisen beim Verarbeiten von Ausnahmen und dem Aufrufen der OnError-Methode verwenden:
Der Anbieter muss seine eigenen Ausnahmen verarbeiten, wenn er spezielle Anforderungen hat.
Der Anbieter sollte nicht erwarten oder voraussetzen, dass Beobachter Ausnahmen auf eine bestimmte Weise verarbeiten.
Der Anbieter sollte die OnError-Methode aufrufen, wenn er eine Ausnahme behandelt, die die Bereitstellung von Updates gefährdet. Informationen zu solchen Ausnahmen können an den Beobachter übergeben werden. In anderen Fällen besteht keine Notwendigkeit, den Beobachter über eine Ausnahme zu benachrichtigen.
Sobald der Anbieter die OnError- oder IObserver<T>.OnCompleted-Methode aufruft, sollte es keine weiteren Benachrichtigungen geben, und der Anbieter kann seine Beobachter kündigen. Allerdings können die Beobachter das Abonnement auch jederzeit selbst kündigen, auch bevor oder nachdem sie eine OnError- oder IObserver<T>.OnCompleted-Benachrichtigung empfangen. Das Beobachterentwurfsmuster schreibt nicht vor, ob der Anbieter oder der Beobachter für die Kündigung zuständig ist; aus diesem Grund besteht die Möglichkeit, dass beide versuchen, zu kündigen. Wenn Beobachter kündigen, werden sie in der Regel aus einer Abonnentenauflistung entfernt. In einer Single-Thread-Anwendung sollte die IDisposable.Dispose-Implementierung sicherstellen, dass ein Objektverweis gültig ist und dass das Objekt ein Mitglied der Abonnentenauflistung ist, bevor der Versuch unternommen wird, es zu entfernen. In einer Multithreadanwendung sollte ein threadsicheres Auflistungsobjekt, z. B. ein System.Collections.Concurrent.BlockingCollection<T>-Objekt, verwendet werden.
Der Beobachter – Implementieren der OnError-Methode
Wenn ein Beobachter eine Fehlerbenachrichtigung von einem Anbieter empfängt, sollte der Beobachter die Ausnahme als Informationsmeldung behandeln und sollte nicht verpflichtet sein, bestimmte Maßnahmen zu ergreifen.
Der Beobachter sollte diesen empfohlenen Vorgehensweisen bei der Reaktion auf einen OnError-Methodenaufruf von einem Anbieter folgen:
Der Beobachter sollte keine Ausnahmen in seinen Schnittstellenimplementierungen auslösen, z. B. OnNext oder OnError. Wenn der Beobachter aber Ausnahmen auslöst, sollte er davon ausgehen, dass diese Ausnahmen nicht behandelt werden.
Um die Aufrufliste beizubehalten, sollte ein Beobachter, der ein Exception-Objekt, das an die OnError-Methode übergeben wurde, auslösen möchte, die Ausnahme vor dem Auslösen umschließen. Zu diesem Zweck sollte ein Standardausnahmeobjekt verwendet werden.
Weitere empfohlene Vorgehensweisen
Der Versuch, die Registrierung in der IObservable<T>.Subscribe-Methode aufzuheben, kann in einem Nullverweis resultieren. Aus diesem Grund wird empfohlen, dieses Verfahren zu vermeiden.
Es ist zwar möglich, einen Beobachter an mehrere Anbieter anzufügen, das empfohlene Muster ist aber das Anfügen einer IObserver<T>-Instanz an nur eine IObservable<T>-Instanz.