2017-04-23 44 views
0

給定一個Observable,一旦調用了Subscribe,就會開始推送事件。如何將序列轉換爲IEnumerable。從IObservable轉換爲IEnumerable的無功擴展

在2010年,Jon Skeet寫到了他對RX的第一印象,並寫道這與我所需要的相當。

public static List<T> ToList<T>(this IObservable<T> source) 
{ 
    List<T> ret = new List<T>(); 
    source.Subscribe(x => ret.Add(x)); 
    return ret; 
} 

https://codeblog.jonskeet.uk/2010/01/16/first-encounters-with-reactive-extensions/

雖然這種解決方案會工作好像應該有一個更好的辦法。

我們真正感興趣的是await可觀察的能力,其行爲與Subscribe類似。

await observable.ToList() 

但是,這似乎不適用於我。

我也看着這兩個方法

observable.ToEnumerable 
observable.Next 

我打算用它來寫一些單元測試多一點信息。

  1. 我正在使用ReplaySubject並用測試替代品執行一系列操作。
  2. 通過OnNext記錄給代理人的電話。
  3. 我可以得到調用列表並聲明它們是正確的。

回答

1

編輯

如果您無法如下所述,然後使用await會沒完沒了地等待完成流。我會以其他方式進行測試。你可以看看Nuget Package Microsoft.Reactive.Testing,其中包含一些強大的測試工具。或者只是使用Subscribe並在那裏斷言。


await等待觀察結束或錯誤輸出。您可能只需要添加OnCompleted致電ReactiveSubject,你應該沒問題。以下代碼適用於我:

var rs = new ReplaySubject<int>(); 

rs.OnNext(1); 
rs.OnNext(2); 
rs.OnNext(3); 
rs.OnCompleted(); 
var l = await rs.ToList(); 

//l is equivalent to new List<int>() {1, 2, 3}; 
+0

我剛纔意識到我沒有辦法完成流 –

+0

已更新的答案。 – Shlomo

+0

它似乎沒有可能在訂閱方法 –

1

有趣的是,Skeet先生的實施非常糟糕。它不會阻止,只有當來源是重播主題(或類似)時,纔會將值抽取到列表中。因此對於大多數可觀察序列,這隻會返回一個空列表。 我相信喬恩知道,但也許在翻譯中迷失了方向。

ToList()是你想要的,所以我假設你可能沒有完成?如果你只想要一個已知數量的元素,那麼Take(x).ToList()就足夠了。