Partilhar via


Práticas recomendadas do padrão de design do observador

No .NET, o padrão de design do observador é implementado como um conjunto de interfaces. A System.IObservable<T> interface representa o provedor de dados, que também é responsável por fornecer uma IDisposable implementação que permite que os observadores cancelem a assinatura de notificações. A System.IObserver<T> interface representa o observador. Este tópico descreve as práticas recomendadas que os desenvolvedores devem seguir ao implementar o padrão de design do observador usando essas interfaces.

Encadeamento

Normalmente, um provedor implementa o IObservable<T>.Subscribe método adicionando um observador específico a uma lista de assinantes que é representada por algum objeto de coleção e implementa o IDisposable.Dispose método removendo um observador específico da lista de assinantes. Um observador pode chamar esses métodos a qualquer momento. Além disso, como o contrato de provedor/observador não especifica quem é responsável por cancelar a assinatura após o IObserver<T>.OnCompleted método de retorno de chamada, o provedor e o observador podem tentar remover o mesmo membro da lista. Devido a essa possibilidade, tanto o quanto os SubscribeDispose métodos devem ser thread-safe. Normalmente, isso envolve o uso de uma coleção simultânea ou um bloqueio. As implementações que não são thread-safe devem documentar explicitamente que não são.

Quaisquer garantias adicionais têm de ser especificadas numa camada adicional ao contrato de fornecedor/observador. Os responsáveis pela execução devem chamar claramente a atenção quando impõem requisitos adicionais para evitar a confusão dos utilizadores sobre o contrato de observador.

Tratamento de exceções

Devido ao acoplamento flexível entre um provedor de dados e um observador, as exceções no padrão de design do observador destinam-se a ser informativas. Isso afeta a forma como os provedores e observadores lidam com exceções no padrão de design do observador.

O provedor — chamando o método OnError

O OnError método pretende ser uma mensagem informativa para os observadores, tal como o IObserver<T>.OnNext método. No entanto, o OnNext método é projetado para fornecer a um observador dados atuais ou atualizados, enquanto o OnError método é projetado para indicar que o provedor é incapaz de fornecer dados válidos.

O provedor deve seguir estas práticas recomendadas ao lidar com exceções e chamar o OnError método:

  • O provedor deve lidar com suas próprias exceções se tiver quaisquer requisitos específicos.

  • O provedor não deve esperar ou exigir que os observadores tratem exceções de qualquer maneira específica.

  • O provedor deve chamar o OnError método quando ele lida com uma exceção que comprometa sua capacidade de fornecer atualizações. As informações sobre essas exceções podem ser transmitidas ao observador. Noutros casos, não é necessário notificar os observadores de uma exceção.

Uma vez que o provedor chama o OnError método ou IObserver<T>.OnCompleted , não deve haver mais notificações, e o provedor pode cancelar a inscrição de seus observadores. No entanto, os observadores também podem cancelar a sua inscrição a qualquer momento, incluindo antes e depois de receberem uma OnError notificação ou IObserver<T>.OnCompleted notificação. O padrão de design do observador não determina se o provedor ou o observador é responsável por cancelar a assinatura; portanto, existe a possibilidade de que ambos tentem cancelar a inscrição. Normalmente, quando os observadores cancelam a inscrição, eles são removidos de uma coleção de assinantes. Em um aplicativo de thread único, a IDisposable.Dispose implementação deve garantir que uma referência de objeto seja válida e que o objeto seja um membro da coleção de assinantes antes de tentar removê-lo. Em um aplicativo multithreaded, um objeto de coleção thread-safe, como um System.Collections.Concurrent.BlockingCollection<T> objeto, deve ser usado.

The Observer—Implementando o método OnError

Quando um observador recebe uma notificação de erro de um provedor, o observador deve tratar a exceção como informativa e não deve ser obrigado a tomar nenhuma ação específica.

O observador deve seguir estas práticas recomendadas ao responder a uma OnError chamada de método de um provedor:

  • O observador não deve lançar exceções de suas implementações de interface, como OnNext ou OnError. No entanto, se o observador lançar exceções, deve esperar que essas exceções não sejam tratadas.

  • Para preservar a pilha de chamadas, um observador que deseja lançar um Exception objeto que foi passado para seu OnError método deve envolver a exceção antes de lançá-la. Um objeto de exceção padrão deve ser usado para essa finalidade.

Práticas recomendadas adicionais

A tentativa de cancelar o IObservable<T>.Subscribe registro no método pode resultar em uma referência nula. Portanto, recomendamos que você evite essa prática.

Embora seja possível anexar um observador a vários provedores, o padrão recomendado é anexar uma IObserver<T> instância a apenas uma IObservable<T> instância.

Consulte também