响应式扩展中的数据服务

3

我希望有一个通用类来处理数据的内存缓存,包括创建、更新和删除。底层模型继承自一个具有字符串类型Id的接口。

interface IModel
{
  string Id { get; }
}

处理创建和更新很容易。例如,如果我想订阅流并填充字典,我知道如果模型ID不存在,则需要创建,否则就是更新。

我的问题是:
如果不引入另一个包装我的模型的类,你会如何处理删除?我想保持一个 IObservable<TModel>,而不是像 IObservable<Event<TModel>>IObservable<Pair<string, TModel>> 这样的东西,但我不知道怎么做。这可能吗?

interface IDataService<TModel>
{
  IObservable<TModel> DataStream { get; }
}

2
您可以使用 IObservable<IObservable<TModel>> 创建嵌套流,这样当每个内部流结束时,在内部流上添加/更新的任何模型都会被删除。 - Enigmativity
听起来很有趣,我没有想过那个。我不确定在使用中它会有多方便,以及它会给实现增加多少额外负担。我会试一试。 - Romain Hautefeuille
1
你只能使用一个流吗?还是可以有多个流? - paulpdaniels
你是在建议为每个操作创建单独的流吗?或者至少为删除专门分配一个流?这也听起来不错! - Romain Hautefeuille
首先,你可以像 ItemChangedItemAddedItemDeleted 这样命名。如果你真的想要,可以将添加和更改组合在一起,但我喜欢通过将它们分开来分离关注点,这样可以避免消费者总是担心他们之前是否看到过一个项目。 - paulpdaniels
1个回答

2
如@Enigmativity所建议的,您可以使用嵌套的可观测序列来解决这个问题。 在IntroToRx的巧合序列部分中有涉及。
这会是怎样工作的呢?
您可以将嵌套序列视为类似于二维数组,甚至更具体地说是不规则数组。 外部序列是内部序列的容器。 内部序列的到达表示模型的创建
interface IDataService<TModel>
{
    IObservable<IObservable<TModel>> DataStream { get; }
}

一旦您有了内部序列,它产生的所有值都是更新(除了第一个值)。内部序列只会为单个ID生成更新。当内部序列完成时,它们表示删除。
这种模式适用于各种用例,如上面链接中的初始段落所概述的那样。
作为弹珠图,您将拥有类似以下的内容。每行代表一个内部序列。
m1  1---2----3--|
m2     a----|
m3       x----y---z--

这将导致以下逻辑流程:
  1. 创建状态为'1'的m1
  2. 创建状态为'a'的m2
  3. 更新m1的值为'2'
  4. 创建值为'x'的m3
  5. 删除m2
  6. 更新m1的值为'3'
  7. 更新m3的值为'y'
  8. 删除m1
  9. 更新m3的值为'z'

抱歉回复晚了,我不得不转到另一个话题。 我在想当这个数据服务流绑定到UI时如何执行缓冲/窗口化?你有什么提示吗?看起来IObs<IObs<T>>在这种情况下不太方便对吧? - Romain Hautefeuille
这是两个不同的问题。首先解决你的建模问题。我建议使用嵌套的可观察序列来解决这个问题。一旦你解决了建模问题,那么你就有了保持UI响应的另一个问题。将其分解为独立的查询。 - Lee Campbell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接