Observable.Generateメソッド3回目 〜終了判定に使った要素も欲しいんですが・・・〜
またまたObservable.Generateメソッドの続き。
前回、コードレシピにサンプルを登録したんだけども(Reactive Extensionsを使用してTwitterから非同期にデータを取得し表示する)、見返してて、というか作ってるうちから自分的にイテてないな〜と思う部分があった。
それは、Observable.Generateメソッドの終了判定でViewModelのFriendsコレクションに結果を追加しているところ。
var o = Observable.Generate( new UsersResult { next_cursor = "-1", users = new List<User>() }, i => { // 終了判定の中でFriendsコレクションに追加するのが非常に気持ち悪い Friends.AddRange(i.users); return i.next_cursor != "0"; }, i => { return client.GetFriends(i.next_cursor); }, i => i, Scheduler.ThreadPool); o.Subscribe( i => { // できればここでFriendsコレクションに追加したい }, ...................
終了判定は終了判定だから、終了判定以外のことはなるべくさせたくない。
Subscribeメソッドの中でできたら良いんだけども・・・。
そもそもなぜ終了判定の中で追加したかっていうと、
Observable.Generateメソッドの引数の呼ばれ方が
var o = Observable.Generate( 1, i => { return i < 5; // 1.終了判定 }, i => { return ++i; // 4.次を呼ぶ処理 }, i => { return i; // 2.セレクタ } ).Subscribe( i => { Console.WriteLine(i); // 3.OnNext } );
のようになっているからで、
- 終了判定が呼ばれ、trueだった場合のみ
- セレクタが呼ばれ、そこで返したものが
- OnNextで受け取れる
というものだから。
つまり、「1.終了判定」以外でないと、終了判定がfalse(サンプルの例で言えばnext_cursorが"0")となった結果は受け取れないのだ。
OnNextは「次の反復処理を呼ぶ前に実行されるもの」という意味だから、当たり前だけど。
じゃあ、終了判定に使った結果は、終了判定以外でどうやって受け取るの?
と調べたけど、どうもできないらしい。(調べ足りないかもなので、できるかた教えてほしい)
コールバックも引数なしだし・・・。
ということで苦肉の策。
var o = Observable.Generate( new UsersResult { next_cursor = "-1", users = new List<User>() }, i => { //終了判定はnullかどうか return i != null; }, i => { //next_cursorが"0"の場合、Apiを呼ばないでnullを返す return i.next_cursor == "0" ? null : client.GetFriends(i.next_cursor); }, i => i, Scheduler.ThreadPool) .Subscribe( i => Friends.AddRange(i.users) );
うーん、まだちょっとイケてない気するけど、前のよりはマシかも。