2013-03-03 30 views
0

我有一個很大的ReplaySubject,它允許訂戶正常接收重播緩衝區和將來的通知。另外,我希望能夠將當前緩衝區的「快照」 作爲一個列表同步返回,而不必訂閱。拍攝ReplaySubject快照<T>緩衝區

有沒有辦法做到這一點?

感謝

回答

1

你能不只是認購,收到的項目,然後退訂?

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<T>調用元素處理同步,當然。你想檢查一下,但這就是我所期望的。

您還應該考慮是否要以某種方式處理錯誤/完成。

+0

我正要來形容,這是錯誤的,因爲主題可能尚未完成,但它實際上是* *僅辦法做到這一點(而不是wron G)。聰明!這就是說,我可能會從ReplaySubject複製源代碼並添加一個明確的方法來執行此操作。 – 2013-03-03 19:48:06

+0

@PaulBetts * only * way .... Feh。從來沒有*只有*一種方式。 ;) – JerKimball 2013-03-04 22:33:55

+0

感謝球員,這工作正常,我只是假設可能有其他東西我失蹤。 – stevebull 2013-03-15 09:50:39

0

ONLY因爲@PaulBetts說,只有一個辦法做到這一點:)

注:我不建議這樣;使用Skeet的方法,你會在以後感謝你。

因此,ReplaySubject<T>的魔力都與它通過內部Queue<TimeInterval<T>>上的OnNext收到的任何值排隊。因此,我們可以編寫撥弄一下週圍的重播主題的私人細節裏面的包裝來獲取信息:

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(); 
    } 
} 

試驗檯:

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(); 
} 

結果: (TimeInterval<T>只是價值+時間它進來)

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