Istnieją interfejsy IObservable i IObserver w .NET (także tu i tutaj ). Co ciekawe, konkretne wdrożenie IObserver nie zawiera bezpośredniego odniesienia do IObservable. Nie wie, kto jest subskrybentem. Może tylko wywołać subskrybenta. „Wyciągnij pinezkę, aby anulować subskrypcję”.
edycja: Subskrybent implementuje IDisposable
. Myślę, że ten schemat został zastosowany, aby zapobiec problemowi z wygasłym słuchaczem .
Jednak dwie rzeczy nie są do końca jasne.
- Czy wewnętrzna klasa Unsubscriber zapewnia zachowanie „zapisz się i zapomnij”? Kto (i kiedy dokładnie) wzywa
IDisposable.Dispose()
abonenta? Garbage collector (GC) nie jest deterministyczny.
[Uwaga: ogólnie, spędziłem więcej czasu z C i C ++ niż z C #.] Co powinno się stać, jeśli chcę subskrybować obserwatora K do obserwowalnego L1, a obserwator jest już subskrybowany do innego obserwowalnego L2?
K.Subscribe(L1); K.Subscribe(L2); K.Unsubscribe(); L1.PublishObservation(1003); L2.PublishObservation(1004);
Kiedy uruchomiłem ten kod testowy na przykładzie MSDN, obserwator pozostał subskrybowany do L1. Byłoby to szczególne w prawdziwym rozwoju. Potencjalnie istnieją 3 sposoby na poprawę tego:
- Jeśli obserwator ma już instancję subskrybenta (tj. Jest już subskrybowany), wówczas cicho wypisuje się z pierwotnego dostawcy przed subskrybowaniem nowego. Takie podejście ukrywa fakt, że nie jest już subskrybentem pierwotnego dostawcy, co może później stać się niespodzianką.
- Jeśli obserwator ma już instancję subskrybenta, zgłasza wyjątek. Dobrze zachowujący się kod wywołujący musi jawnie wypisać się z listy obserwatorów.
- Obserwator subskrybuje wielu dostawców. Jest to najbardziej intrygująca opcja, ale czy można to zaimplementować za pomocą IObservable i IObserver? Zobaczmy. Obserwator może przechowywać listę obiektów niesubskrybujących: po jednym dla każdego źródła. Niestety
IObserver.OnComplete()
nie udostępnia referencji dostawcy, który ją wysłał. Tak więc implementacja IObserver z wieloma dostawcami nie byłaby w stanie określić, z którego z nich zrezygnować.
Czy IObserver .NET był przeznaczony do subskrybowania wielu IObservables?
Czy podręcznikowa definicja wzorca obserwatora wymaga, aby jeden obserwator mógł subskrybować wielu dostawców? Czy jest to opcjonalne i zależy od implementacji?