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

のようになっているからで、

  1. 終了判定が呼ばれ、trueだった場合のみ
  2. セレクタが呼ばれ、そこで返したものが
  3. 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)
    );

うーん、まだちょっとイケてない気するけど、前のよりはマシかも。