public IDisposable Subscribe(IObserver <ListChange <T> > observer) { var mapper = new WhereChangeMapper(); var gate = new object(); return(_source.Subscribe( Observer.Create <ListChange <T> >( onNext: change => { lock (gate) { var newChanges = new List <ListChange <T> >(); change( insert: (index, item) => newChanges.AddRange(mapper.Insert(index, item, _predicate(item))), replace: (index, item) => newChanges.AddRange(mapper.Replace(index, item, _predicate(item))), remove: index => newChanges.AddRange(mapper.Remove <T>(index)), clear: () => newChanges.AddRange(mapper.Clear <T>())); if (newChanges.Count > 0) { observer.OnNext(ListChange.Combine(newChanges)); } } }, onCompleted: observer.OnCompleted, onError: observer.OnError))); }
public void OnNext(ListChange <IObservable <T> > changes) { lock (_gate) { changes( insert: (index, obs) => { var indexedItem = new IndexTrackerList <SingleAssignmentDisposable> .IndexedItem(new SingleAssignmentDisposable()); _innerSubscriptions.Insert(index, indexedItem); _changeMapper.InsertFalse(index); _innerCompleted = _innerCompleted.Insert(index, false); indexedItem.Value.Disposable = SubscribeInner(obs, indexedItem); }, replace: (index, obs) => { _innerSubscriptions[index].Dispose(); var indexedItem = new IndexTrackerList <SingleAssignmentDisposable> .IndexedItem(new SingleAssignmentDisposable()); _innerSubscriptions.Replace(index, indexedItem); _innerCompleted = _innerCompleted.ReplaceAt(index, false); indexedItem.Value.Disposable = SubscribeInner(obs, indexedItem); // The new observable hasn't produced any values left, so remove any leftover old values foreach (var change in _changeMapper.ReplaceFalse <T>(index)) { _observer.OnNext(change); } }, remove: (index) => { _innerSubscriptions[index].Dispose(); _innerSubscriptions.Remove(index); _innerCompleted = _innerCompleted.RemoveAt(index); foreach (var change in _changeMapper.Remove <T>(index)) { _observer.OnNext(change); } }, clear: () => { Disposable.Combine(_innerSubscriptions).Dispose(); _innerSubscriptions.Clear(); _innerCompleted = SumTree <bool> .Empty(false, (d1, d2) => d1 && d2); foreach (var change in _changeMapper.Clear <T>()) { _observer.OnNext(change); } }); } }