合并不断变化的可观察集合

时间:2017-02-09 01:35:55

标签: system.reactive

我们有一个实现Thing的课程IObservable<Thing>。在另一个类中,有一个Thing的集合,该类需要以统一的方式对来自所有这些可观察对象的更新做出反应。显而易见的方法是Observable.Merge(),这通常有效; 然而,当集合发生变化时,我们还需要订阅我们合并订阅中的任何新Thing(理论上取消订阅所有已删除的订阅,但这似乎不那么成问题 - 他们只是不会再产生任何更新了。)

我们目前通过在集合的每次更改时重新创建订阅来实现这一目标,但这在处理开销方面似乎相当不理想,而且由于在丢弃之间的短暂时间内缺少任何Thing的更新旧订阅并创建新订阅(事实证明这是一个问题,特别是因为我们还需要在短时间内Buffer()订阅,并且在处理订阅时丢失缓冲的项目)

合并这样一个不断变化的可观察集合的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

如果你有一个IObservable<IObservable<T>> observable,那么就打电话给Merge就会包括新父母的孩子,如果你抓住了我的漂移。诀窍是将ObservableCollection<IObservable<Thing>>转换为IObservable<IObservable<Thing>>

如果您正在运行ReactiveUI,并且可以使用它,那么您可以将ObservableCollection<IObservable<Thing>>转换为ReactiveCollection<IObservable<Thing>>ReactiveCollection继承自ObservableCollection,并且还实现了IObservable

如果ReactiveUI是不可能的(我猜这是因为你已经在使用Caliburn Micro集合),那么你可以使用ObservableCollection的事件进行转换:

ObservableCollection<IObservable<Thing>> observableCollection = new ObservableCollection<IObservable<Thing>>();
IObservable<IObservable<Thing>> oCollectionObservable = Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
    h => observableCollection.CollectionChanged += h,
    h => observableCollection.CollectionChanged -= h
)
    .SelectMany(ep => ep.EventArgs.NewItems.Cast<IObservable<Thing>>());

以下是一些演示用法的示例代码:

oCollectionObservable
    .Merge()
    .Subscribe(t => Console.WriteLine($"Received Thing {{Id = {t.Id}}}"));

var firstObservable = Observable.Range(1, 5)
    .Select(i => new Thing { Id = i })
    .Concat(
        Observable.Range(8, 5)
            .Select(i => new Thing { Id = i })
            .Delay(TimeSpan.FromSeconds(2))
    );

observableCollection.Add(firstObservable);
var subject = new Subject<Thing>();
observableCollection.Add(subject);
subject.OnNext(new Thing { Id = 6 });
subject.OnNext(new Thing { Id = 7 });

使用以下课程:

public class Thing
{
    public int Id { get; set; }
}