【发布时间】:2020-03-30 02:33:43
【问题描述】:
我有以下结构:
// source of data
interface IItem
{
IObservable<string> Changed { get; }
}
interface IItemCollection
{
List<IItem> Items { get; }
IObservable<IItem> ItemAdded { get; }
IObservable<IItem> ItemRemoved { get; }
}
interface IItemCollectionManager
{
List<IItemCollection> ItemCollectionCollection { get; }
IObservable<IItemCollection> ItemCollectionAdded { get; }
IObservable<IItemCollection> ItemCollectionRemoved { get; }
}
// desired result
interface IAggregation
{
IObservable<string> Changed { get; }
}
这里的目标是让IAggregation 公开单个可观察对象。但是,IItems 可以随时从每个IItemCollection 添加和删除,事实上,IItemCollection 也可以随时从IItemCollectionManager 添加或删除。当然,当添加了这样的IItemCollection 时,Aggregation 也应该从那个中发出值,如果删除了 ItemCollection,我不再需要该集合中 IItems 中的 strings被发射。此外,当Item 被添加到任何IItemCollection 时,来自其Changed observable 的值也应该产生来自IAggregation 的Changed observable 的值。
现在,当只有一个 IItemCollection 时,解决这个问题相当简单,例如像这样:
class AggregationImpl : IAggregation
{
public AggregationImpl(IItemCollection itemCollection)
{
var added = itemCollection.ItemAdded
.Select(_ => itemCollection.Items);
var removed = itemCollection.ItemRemoved
.Select(_ => itemCollection.Items);
Changed = Observable.Merge(added, removed)
.StartWith(itemCollection.Items)
.Select(coll => coll.Select(item => item.Changed).Merge())
.Switch();
}
public IObservable<string> Changed { get; }
}
...这里的关键点是我将所有Item 的Changed 可观察对象扁平化为带有Merge() 的单个可观察对象,然后,每次添加或删除项目时,我都会重新创建整个Observable 并使用Switch() 退订旧的并订阅新的`。
我觉得扩展以包含 IItemCollectionManager 应该很简单,但我不太确定如何处理它。
【问题讨论】:
-
IItem和IAggregation的接口是一样的,是这个意思吗? -
可以选择使用
SelectMany()吗? -
@程序。是的,有意的。有第三方希望消费
IAggregations observable,但是IAggregation必须完成从正确的Items 发射值的工作,无论它们何时出现和消失(即使这意味着添加了一个项目或删除,或添加或删除整个项目集合)。 -
@Progman。
System.Reactive.Linq中的所有内容都是一个选项 - 它以一种有用的方式将它们组装在一起,在这种情况下很棘手。SelectMany不能单独工作。我几乎可以肯定我至少需要一个Switch()才能让它工作。 -
你可以使用来自DynamicData 的
SourceList吗?由于您正在使用列表和 Rx,您可能想看看这个库。
标签: c# system.reactive