store在Rx中检索IObservable订阅状态

时间:2012-04-10 12:55:00

标签: c# .net serialization persistence system.reactive

[此问题属于Reactive Extensions (Rx) ]

需要在应用程序重新启动时继续的订阅

int nValuesBeforeOutput = 123;

myStream.Buffer(nValuesBeforeOutput).Subscribe(
    i => Debug.WriteLine("Something Critical on Every 123rd Value"));

现在我需要序列化和反序列化此订阅的状态,以便下次启动应用程序时,缓冲区计数不会从零开始,而是从应用程序退出之前的缓冲区计数开始

  • 在这种情况下你怎么能坚持IObservable.Subscribe()的状态然后加载呢?
  • 是否有在Rx中保存观察者状态的一般解决方案?



从答案到解决方案

基于Paul Betts的方法,这是一个半概括的实现,在我的初始测试中起作用

使用

int nValuesBeforeOutput = 123;

var myRecordableStream = myStream.Record(serializer);
myRecordableStream.Buffer(nValuesBeforeOutput).ClearRecords(serializer).Subscribe(
    i => Debug.WriteLine("Something Critical on Every 123rd Value"));

扩展方法

    private static bool _alreadyRecording;

    public static IObservable<T> Record<T>(this IObservable<T> input,
                                           IRepositor repositor) 
    {
        IObservable<T> output = input;
        List<T> records = null;
        if (repositor.Deserialize(ref records))
        {
            ISubject<T> history = new ReplaySubject<T>();
            records.ForEach(history.OnNext);
            output = input.Merge(history);
        }
        if (!_alreadyRecording)
        {
            _alreadyRecording = true;
            input.Subscribe(i => repositor.SerializeAppend(new List<T> {i}));
        }
        return output;
    }

    public static IObservable<T> ClearRecords<T>(this IObservable<T> input,
                                                 IRepositor repositor)
    {
        input.Subscribe(i => repositor.Clear());
        return input;
    }

注释

  • 这不适用于存储依赖于生成的值之间的时间间隔的状态
  • 您需要一个支持序列化T
  • 的序列化程序实现 如果您多次订阅_alreadyRecording ,则需要
  • myRecordableStream
  • _alreadyRecording是一个静态布尔值,非常难看,并且如果需要并行订阅,则可以防止扩展方法在多个地方使用 - 需要重新实现以备将来使用

1 个答案:

答案 0 :(得分:1)

对此没有通用解决方案,并且制作一个是NonTrivial™。你可以做的最接近的事情是让myStream进行某种重放Observable(即不是序列化状态,序列化myStream的状态并重做工作让你回到原来的位置)。