Osvědčené postupy pro vzor návrhu pozorovatele

V .NET se vzor návrhu pozorovatele implementuje jako sada rozhraní. Rozhraní System.IObservable<T> představuje poskytovatele dat, který je také zodpovědný za poskytování IDisposable implementace, která umožňuje pozorovatelům odhlásit odběr oznámení. Rozhraní System.IObserver<T> představuje pozorovatele.

Tento článek popisuje osvědčené postupy, které se mají dodržovat při implementaci vzoru návrhu pozorovatele s těmito rozhraními.

Zvažte alternativy před implementací

Rozhraní IObservable<T> a IObserver<T> jsou vhodná pro scénáře nabízených oznámení, ale jiné vzory .NET můžou být vhodnější. Pro jednoduché oznámení v rámci jedné aplikace použijte události. Pro asynchronní posloupnosti s pull modelem, kde konzument určuje tempo, použijte IAsyncEnumerable<T>. Pro vzory producent–spotřebitel se zpětným tlakem použijte System.Threading.Channels. Pro komplexní skládání, filtrování a transformaci událostí použijte balíček System.Reactive (Rx.NET) namísto přímé implementace IObservable<T>. Další informace naleznete v tématu Vzor návrhu pozorovatele.

Použijte samostatný typ pro data oznámení

Objekt obsahující data, která zprostředkovatel odesílá do svých pozorovatelů, odpovídá parametru IObservable<T> obecného typu a IObserver<T>. I když tento objekt může být stejný jako IObservable<T> implementace, definujte ho jako samostatný typ. Vyhrazený datový typ zachovává povinnosti poskytovatele odděleně od datové části oznámení a usnadňuje vývoj rozhraní API.

Nespoléhejte na pořadí oznámení

Pořadí, ve kterém pozorovatelé přijímají oznámení, není definováno. Poskytovatel může použít libovolnou metodu k určení pořadí, takže nezapisujte pozorovatele, kteří závisí na tom, že budou upozorněni před nebo po jiném pozorovateli.

Přihlášení k odběru a odstranění bezpečného vlákna

Zprostředkovatel obvykle implementuje metodu IObservable<T>.Subscribe přidáním pozorovatele do seznamu odběratelů, který je reprezentován objektem kolekce, a implementuje metodu IDisposable.Dispose odebráním pozorovatele z daného seznamu. Pozorovatel může tyto metody kdykoli volat. Smlouva zprostředkovatele nebo pozorovatele neurčuje, kdo je zodpovědný za zrušení odběru IObserver<T>.OnCompleted po metodě zpětného volání, takže se poskytovatel a pozorovatel mohou pokusit odebrat stejného člena ze seznamu.

Abyste se vyhnuli podmínkám časování, zajistěte bezpečnost vláken i SubscribeDispose metod. Obvykle se to týká použití souběžné kolekce nebo zámku. Implementace, které nejsou bezpečné pro přístup z více vláken, by měly explicitně zdokumentovat, že nejsou.

Zdokumentovat všechny záruky dodatečných smluv

Zadejte všechny dodatečné záruky ve vrstvě nad kontraktem poskytovatele/pozorovatele. Pokud stanovíte další požadavky, jasně je uveďte, aby uživatelé neměli nejasnosti ohledně smlouvy pozorovatele.

Zpracování výjimek jako informačních

Vzhledem k volnému spojení mezi poskytovatelem dat a pozorovatelem jsou výjimky v vzoru návrhu pozorovatele určené jako informativní. Tato charakteristika ovlivňuje způsob, jakým poskytovatelé a pozorovatelé zpracovávají výjimky.

Volejte onError pouze tehdy, když aktualizace nemohou pokračovat

Metoda OnError je určena jako informační zpráva pozorovatelům, podobně jako metoda IObserver<T>.OnNext . Metoda OnNext však poskytuje pozorovateli aktuální nebo aktualizovaná data, zatímco OnError metoda označuje, že zprostředkovatel nemůže poskytnout platná data.

Při zpracování výjimek a volání OnError metody postupujte podle těchto osvědčených postupů:

  • Poskytovatel musí zpracovávat vlastní výjimky, pokud má nějaké specifické požadavky.
  • Poskytovatel by neměl očekávat ani vyžadovat, aby pozorovatelé zpracovávali výjimky jakýmkoli konkrétním způsobem.
  • Poskytovatel by měl metodu OnError volat, když zpracovává výjimku, která ohrožuje jeho schopnost poskytovat aktualizace. Předejte pozorovateli informace o těchto výjimkách. V jiných případech není nutné informovat pozorovatele o výjimce.

Poté, co poskytovatel zavolá metodu OnError nebo IObserver<T>.OnCompleted, neměla by již následovat žádná další oznámení a poskytovatel může zrušit odběr svých pozorovatelů. Pozorovatelé se ale můžou kdykoliv odhlásit, a to i před a po přijetí OnError oznámení.IObserver<T>.OnCompleted Vzor návrhu pozorovatele neurčuje, jestli je poskytovatel nebo pozorovatel zodpovědný za zrušení odběru, takže se oba můžou pokusit o odhlášení odběru. Obvykle, když pozorovatelé zruší odběr, jsou odebráni z kolekce odběratelů. V jednovláknové aplikaci IDisposable.Dispose by implementace měla zajistit, aby reference na objekt byla platná a objekt byl členem kolekce odběratelů, než se pokusí tento objekt odebrat. V vícevláknové aplikaci použijte zámek k ochraně kolekce pozorovatelů.

Považujte upozornění OnError v pozorovatelích jako informativní

Když pozorovatel obdrží od poskytovatele oznámení o chybě, měl by s výjimkou zacházet jako s informačními zprávami a neměl by být nutný k provedení konkrétní akce.

Při reakci na OnError volání metody od poskytovatele postupujte podle těchto osvědčených postupů:

  • Nevyvolávejte výjimky v implementacích rozhraní, například OnNext nebo OnError. Pokud pozorovatel vyvolá výjimky, počítejte s tím, že tyto výjimky budou neošetřené.
  • Chcete-li zachovat zásobník volání, pozorovatel, který chce vyvolat Exception objekt, který byl předán jeho OnError metodě, by měl zabalit výjimku před jeho vyvolání. Pro tento účel použijte standardní objekt výjimky.

V metodě Subscribe se neodhlašujte.

Nepokoušejte se zrušit registraci v IObservable<T>.Subscribe metodě, protože může vést k nulovému odkazu.

Připojení pozorovatele k jednomu poskytovateli

I když můžete připojit pozorovatele k více poskytovatelům, doporučeným vzorem je připojit IObserver<T> instanci pouze k jedné IObservable<T> instanci.