Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 拍摄ReplaySubject的快照<;T>;缓冲器_.net_System.reactive - Fatal编程技术网

.net 拍摄ReplaySubject的快照<;T>;缓冲器

.net 拍摄ReplaySubject的快照<;T>;缓冲器,.net,system.reactive,.net,System.reactive,我有一个大型ReplaySubject,它允许订阅者像平常一样接收replay缓冲区和未来的通知。此外,我希望能够拍摄“快照” 并将其作为列表同步返回,而无需订阅 有办法做到这一点吗 谢谢您能不能先订阅、接收项目,然后取消订阅 public static List<T> Snapshot<T>(ReplaySubject<T> subject) { List<T> snapshot = new List<T>(); us

我有一个大型ReplaySubject,它允许订阅者像平常一样接收replay缓冲区和未来的通知。此外,我希望能够拍摄“快照” 并将其作为列表同步返回,而无需订阅

有办法做到这一点吗


谢谢

您能不能先订阅、接收项目,然后取消订阅

public static List<T> Snapshot<T>(ReplaySubject<T> subject)
{
    List<T> snapshot = new List<T>();
    using (subject.Subscribe(item => snapshot.Add(item))
    {
        // Deliberately empty; subscribing will add everything to the list.
    }
    return snapshot;
}
公共静态列表快照(ReplaySubject主题)
{
列表快照=新列表();
使用(subject.Subscribe(item=>snapshot.Add(item))
{
//故意清空;订阅会将所有内容添加到列表中。
}
返回快照;
}
当然,这是假设订阅
ReplaySubject
会同步调用元素处理程序


您还应该考虑是否要处理错误/完成。< /P> < P> <强>仅< <强> >,因为@ PaulBetts说只有一种方法:< /P> 注意:我不推荐这种方式;使用双向飞碟的方法,你会感谢你自己

因此,
ReplaySubject
的神奇之处在于,它将通过
OnNext
接收到的任何值排队到内部
队列上。因此,我们可以编写一个包装器,在replay主题的私有详细信息中四处摆弄,以获取该信息:

public class FixedReplaySubject<T> : ISubject<T>
{
    private ReplaySubject<T> _inner;
    private Func<Queue<TimeInterval<T>>> _snapshotGetter;

    public FixedReplaySubject(ReplaySubject<T> source)
    {
        _inner = source;
        var expr = Expression.Lambda(
            typeof(Func<Queue<TimeInterval<T>>>), 
            Expression.Field(
                Expression.Constant(source), 
                source.GetType()
                    .GetField("_queue", BindingFlags.NonPublic|BindingFlags.Instance)));
        _snapshotGetter = (Func<Queue<TimeInterval<T>>>)expr.Compile();
    }

    public IEnumerable<TimeInterval<T>> Snapshot()
    {
        return _snapshotGetter();
    }

    public IDisposable Subscribe(IObserver<T> observer)
    {
        return _inner.Subscribe(observer);
    }
    public void OnNext(T value)
    {
        _inner.OnNext(value);
    }
    public void OnCompleted()
    {
        _inner.OnCompleted();
    }
    public void OnError(Exception error)
    {
        _inner.OnError(error);
    }
    public void Dispose()
    {
        _inner.Dispose();
    }
}

我正要描述这是错误的,因为这个主题可能还没有完成,但实际上这是唯一的方法(并且没有错)。聪明!也就是说,我可能会从ReplaySubject复制源代码,并添加一个显式方法来实现这一点。谢谢各位,这很好,我只是假设我还缺少其他东西。
void Main()
{
    var src = new ReplaySubject<int>();
    src.OnNext(1);
    src.OnNext(2);
    src.OnNext(3);
    src.OnNext(4);
    src.OnNext(5);
    src.OnNext(6);
    var heh = new FixedReplaySubject<int>(src);
    heh.Snapshot().Dump();
}
1 00:00:00.0010265 
2 00:00:00.0010278 
3 00:00:00.0010278 
4 00:00:00.0010282 
5 00:00:00.0010282 
6 00:00:00.0010286