C# 从流中去除嵌套的可观测数据
我有一个类C# 从流中去除嵌套的可观测数据,c#,system.reactive,reactive-programming,C#,System.reactive,Reactive Programming,我有一个类ObservableCollection,它表示一个不断变化的集合: public interface IObservableCollection<T> : IObservable<IEnumerable<T>> { void Add(T item); void Remove(T item); } var peoplePositions = (from people in peopleCollectionStream
ObservableCollection
,它表示一个不断变化的集合:
public interface IObservableCollection<T> : IObservable<IEnumerable<T>>
{
void Add(T item);
void Remove(T item);
}
var peoplePositions = (from people in peopleCollectionStream
select
(from person in people
select person.Position
.Select(pos => Tuple.Create(person.Name, pos))
).CombineLatest()
).Switch();
我想做的是生成一个IEnumerable
流,表示每个人在集合中的位置。这似乎相对简单:
var peopleCollectionStream = new ObservableCollection<IPerson>();
var peoplePositions = from people in peopleCollectionStream
from updateList in
(from person in people
select person.Position.Select(pos => Tuple.Create(person.Name, pos)))
.CombineLatest()
select updateList;
我得到了期望的输出:
var alice = new Person() { Name = "Alice" };
peopleCollectionStream.Add(alice); // Alice -> 0
alice.Move(2); // Alice -> 2
var bob = new Person() { Name = "Bob" };
peopleCollectionStream.Add(bob); // Alice -> 2, Bob -> 0
bob.Move(3); // Alice -> 2, Bob -> 3
当我希望从集合中删除一个人,从而从流中排除他们的更新时,会出现问题:
peopleCollectionStream.Remove(bob); // Alice -> 2
bob.Move(4); // Alice -> 2, Bob -> 4
我想阻止鲍勃的位置更新被包括,如果他从集合中删除。我怎样才能做到这一点呢?我发现,如果您想做这些功能性的事情,尝试使用添加和删除事件是一个坏主意。匹配删除和添加,并确保底层代码也这样做,这是一项艰巨的工作 我所做的是使用易腐物品/收藏品。我将每个项与一个生存期(取消令牌)配对,当其生存期结束时,该项被视为已删除。然后我用这些生命来连接其他东西。我使用了一种称为
易腐收集
的收集类型,它将项目与生命周期配对,并允许您将其内容作为IObservable
进行查看
我,并发表了一篇论文
下面的代码应该将易腐集合中的易腐集合展平:
public static PerishableCollection<T> Flattened<T>(this PerishableCollection<PerishableCollection<T>> collectionOfCollections, Lifetime lifetimeOfResult) {
if (collectionOfCollections == null) throw new ArgumentNullException("collectionOfCollections");
var flattenedCollection = new PerishableCollection<T>();
collectionOfCollections.CurrentAndFutureItems().Subscribe(
c => c.Value.CurrentAndFutureItems().Subscribe(
// OnItem: include in result, but prevent lifetimes from exceeding source's lifetime
e => flattenedCollection.Add(
item: e.Value,
lifetime: e.Lifetime.Min(c.Lifetime)),
// subscription to c ends when the c's lifetime ends or result is no longer needed
c.Lifetime.Min(lifetimeOfResult)),
// subscription ends when result is no longer needed
lifetimeOfResult);
return flattenedCollection;
}
希望这足以让您开始一条更简单的道路。我发现,如果您想做这些功能性的事情,尝试使用添加和删除事件是一个坏主意。匹配删除和添加,并确保底层代码也这样做,这是一项艰巨的工作 我所做的是使用易腐物品/收藏品。我将每个项与一个生存期(取消令牌)配对,当其生存期结束时,该项被视为已删除。然后我用这些生命来连接其他东西。我使用了一种称为
易腐收集
的收集类型,它将项目与生命周期配对,并允许您将其内容作为IObservable
进行查看
我,并发表了一篇论文
下面的代码应该将易腐集合中的易腐集合展平:
public static PerishableCollection<T> Flattened<T>(this PerishableCollection<PerishableCollection<T>> collectionOfCollections, Lifetime lifetimeOfResult) {
if (collectionOfCollections == null) throw new ArgumentNullException("collectionOfCollections");
var flattenedCollection = new PerishableCollection<T>();
collectionOfCollections.CurrentAndFutureItems().Subscribe(
c => c.Value.CurrentAndFutureItems().Subscribe(
// OnItem: include in result, but prevent lifetimes from exceeding source's lifetime
e => flattenedCollection.Add(
item: e.Value,
lifetime: e.Lifetime.Min(c.Lifetime)),
// subscription to c ends when the c's lifetime ends or result is no longer needed
c.Lifetime.Min(lifetimeOfResult)),
// subscription ends when result is no longer needed
lifetimeOfResult);
return flattenedCollection;
}
希望这足以让您从一条更容易的道路开始。答案是
.Switch
操作符。通过仅选择要订阅的最新观测值列表,流将排除最新版本集合中不存在的任何观测值:
public interface IObservableCollection<T> : IObservable<IEnumerable<T>>
{
void Add(T item);
void Remove(T item);
}
var peoplePositions = (from people in peopleCollectionStream
select
(from person in people
select person.Position
.Select(pos => Tuple.Create(person.Name, pos))
).CombineLatest()
).Switch();
(顺便说一句,如果有人对使用括号/嵌套linq查询语法时的格式有什么好的建议,请告诉我,因为上面看起来很糟糕!)答案是
.Switch
运算符。通过仅选择要订阅的最新观测值列表,流将排除最新版本集合中不存在的任何观测值:
public interface IObservableCollection<T> : IObservable<IEnumerable<T>>
{
void Add(T item);
void Remove(T item);
}
var peoplePositions = (from people in peopleCollectionStream
select
(from person in people
select person.Position
.Select(pos => Tuple.Create(person.Name, pos))
).CombineLatest()
).Switch();
(顺便说一句,如果有人对使用括号/嵌套linq查询语法时的格式有什么好的建议,请告诉我,因为上面的内容看起来非常糟糕!)这是一个非常有趣的概念,谢谢-我必须进一步研究它,看看它是否适用于我的情况。尼斯博客牙齿是一个非常有趣的概念,谢谢你-我将进一步研究它,看看它是否适用于我的情况。很好的博客评论你的推荐请求。两件事:1)我会使用来自。。。从语法(对于SelectMany)而不是最里面的。选择。第二,当嵌套变得过于复杂时,考虑将其重构成单独的方法。如果您使用匿名类型,这会变得很困难,但至少在本例中您看起来是安全的。谢谢,可靠的建议。我不经常使用查询语法,但我发现嵌套时更容易编写。在我的演示项目中,我实际上使用的是匿名类型,但在实际场景中,我肯定会将这些块分割成方法,并使用专用的结构。对您的建议请求进行评论。两件事:1)我会使用来自。。。从语法(对于SelectMany)而不是最里面的。选择。第二,当嵌套变得过于复杂时,考虑将其重构成单独的方法。如果您使用匿名类型,这会变得很困难,但至少在本例中您看起来是安全的。谢谢,可靠的建议。我不经常使用查询语法,但我发现嵌套时更容易编写。在我的演示项目中,我实际上使用的是匿名类型,但在实际场景中,我肯定会将这些块分割成方法,并使用专用结构。