В .NET есть интерфейсы IObservable и IObserver (также здесь и здесь ). Интересно, что конкретная реализация IObserver не содержит прямой ссылки на IObservable. Он не знает, на кого он подписан. Это может только вызвать отписчика. «Пожалуйста, потяните за булавку, чтобы отписаться».
редактировать: отписчик реализует IDisposable
. Я думаю, эта схема была использована для предотвращения проблемы с прослушиванием .
Две вещи мне не совсем понятны.
- Обеспечивает ли внутренний класс Unsubscriber поведение подписки и забывания? Кто (и когда именно) звонит
IDisposable.Dispose()
Unsubscriber? Сборщик мусора (GC) не является детерминированным.
[Отказ от ответственности: в целом, я провел больше времени с C и C ++, чем с C #.] Что должно произойти, если я хочу подписать наблюдателя K на наблюдаемый L1, а наблюдатель уже подписан на какой-то другой наблюдаемый L2?
K.Subscribe(L1); K.Subscribe(L2); K.Unsubscribe(); L1.PublishObservation(1003); L2.PublishObservation(1004);
Когда я запускал этот тестовый код на примере MSDN, наблюдатель оставался подписанным на L1. Это было бы особенным в реальном развитии. Потенциально, есть 3 пути для улучшения этого:
- Если у наблюдателя уже есть экземпляр отписчика (т. Е. Он уже подписан), то он тихо отписывается от исходного провайдера перед подпиской на нового. Этот подход скрывает тот факт, что он больше не подписан на первоначального поставщика, что может стать неожиданностью позже.
- Если у наблюдателя уже есть экземпляр отписчика, он вызывает исключение. Правильный код вызова должен явно отписаться от наблюдателя.
- Обозреватель подписывается на несколько поставщиков. Это наиболее интригующий вариант, но может ли он быть реализован с помощью IObservable и IObserver? Посмотрим. Наблюдатель может вести список неподписанных объектов: по одному для каждого источника. К сожалению,
IObserver.OnComplete()
не предоставляет ссылку обратно поставщику, который его отправил. Таким образом, реализация IObserver с несколькими провайдерами не сможет определить, от кого отписаться.
Был ли IObserver .NET предназначен для подписки на несколько IObserable?
Требуется ли из определения шаблона наблюдателя в учебнике, что один наблюдатель должен иметь возможность подписаться на несколько поставщиков? Или это необязательно и зависит от реализации?
источник
using
блок. Стоимость оператора подписки должна быть практически равна нулю, так что вы бы блокировали блок использования, подписывались, оставляли блок использования (таким образом, отписывались), делая код довольно бессмысленнымВы правы. Пример плохо работает для нескольких IObservables.
Я предполагаю, что OnComplete () не предоставляет обратную ссылку, потому что они не хотят, чтобы IObservable сохранял его. Если бы я писал, что, вероятно, я бы поддержал несколько подписок, если бы Subscribe принимала идентификатор в качестве второго параметра, который передается обратно в вызов OnComplete (). Так что вы могли бы сказать,
Похоже, что .NET IObserver не подходит для нескольких наблюдателей. Но я полагаю, что ваш основной объект (в данном примере LocationReporter) может иметь
и это позволит вам поддержать
также.
Я полагаю, что Microsoft может утверждать, что, следовательно, им нет необходимости напрямую поддерживать несколько IObservables в интерфейсах.
источник
IObserver.OnComplete()
это не определяет, от кого поступил звонок. Если наблюдатель подписан на несколько наблюдаемых, он не знает, от кого отписаться. Разочаровывающим. Интересно, есть ли .NET лучший интерфейс для шаблона наблюдателя?Observable.Create()
для создания наблюдаемой, и используя для этого несколько исходных наблюдаемыхSubscribe()
. Я случайно передал завершенную наблюдаемую в одном пути кода. Это завершило мою недавно созданную наблюдаемую, хотя другие источники не были завершены. Мне понадобились целые годы, чтобы понять, что мне нужно сделать - переключитьсяObservable.Empty()
наObservable.Never()
.Я знаю , что это путь поздно к партии, но ...
Интерфейсы I
Observable<T>
иIObserver<T>
являются не частью Rx ... они являются основными типами ... но Rx широко использует их.Вы можете иметь столько наблюдателей, сколько захотите. Если вы ожидаете нескольких наблюдателей, то наблюдаемая обязанность направлять
OnNext()
вызовы соответствующим наблюдателям для каждого наблюдаемого события. Наблюдаемой может потребоваться список или словарь, как вы предлагаете.Есть хорошие случаи для разрешения только одного - и хорошие случаи для разрешения многих. Например, в реализации CQRS / ES вы можете использовать один обработчик команд для каждого типа команд на командной шине, в то время как вы можете уведомить несколько преобразований на стороне чтения для данного события. типа в хранилище событий.
Как указано в других ответах, нет
Unsubscribe
. Избавление от того, что вам дают, когда выSubscribe
обычно делаете грязную работу. Наблюдатель или его агент отвечает за удержание токена до тех пор, пока он больше не захочет получать дальнейшие уведомления. . (вопрос 1)Итак, в вашем примере:
... это было бы больше похоже на:
... где K услышит 1003 и 1004, но не 1005.
Для меня это все еще выглядит забавно, потому что номинально подписки являются долгоживущими вещами ... часто на время действия программы. В этом отношении они не похожи на обычные .Net события.
Во многих примерах, которые я видел,
Dispose
маркер действительно удаляет наблюдателя из списка наблюдаемых. Я предпочитаю, чтобы токен не обладал таким большим знанием ... и поэтому я обобщил свои токены подписки, чтобы просто вызвать переданную лямбду (с идентифицирующей информацией, получаемой во время подписки:... и наблюдаемое может установить поведение отказа от подписки во время подписки:
Если ваш наблюдатель отлавливает события из нескольких наблюдаемых, вы можете убедиться, что в самих событиях есть какая-то информация о корреляции ... как .Net события делают с
sender
. Это зависит от вас, имеет ли это значение или нет. Это не запечено, как вы правильно рассуждали. (вопрос 3)источник