2011年10月27日木曜日

非同期で結果を受け取る

WindowsPhoneの非同期処理の理念は伝わっているけど、、、
C#の言語理解が足りないから実装方法がわからない。
GoogleのAPIの実装を見た時に「うわっこんな実装になるのか。。。なんで?」って
ところが理解できてなかったと再度思うことになった。
何がしたいか?
WindowsPhoneでGoogle+にアクセスしたい。
そこで処理を書いていくと

1.OAuthの部分(+その後の処理)をGUIと切り離したいのでライブラリ化しておきたい。
 -だけどアクセスは非同期処理になるので、データが返ってくるタイミングがわからない。
2.なのでそのデータをどう使うかはPhone側関数の処理にしたい。
3.その関数の引数はJsonの生データ(string)ではなくて、型が決まった状態で受け取りたい。
 -Newtonsoft.JsonのDeserializeObject()を呼び出すのでT型で呼び出したい。

この位の知識で実装してたら、あれ?あれ?って感じになったのでまとめておく。
レスポンスデータ取得後の呼び出し
最終的にT型で関数を呼び出すという目標に対して、
レスポンスが受けとったデータを呼び出すので
        public IJsonResult target;

        string = {レスポンスデータ};
        target.SendJson(data);
みたいな実装が必要なのでまずインターフェースを定義してみた。
これは生成時にT型が必要なのですが、呼び出し時にtargetをインスタンス化する為です。
SendJson()の実装
で、SendJson()の実装はジェネリックを利用して
    public class JsonResult<T> : Ziro.OAuth.IJsonResult where T : JsonData 
    {
        private Action<T> action;
        public JsonResult(Action<T> lambda )
        {
            action = lambda;
        }
        
        public void SendJson(string responseData) {
            //データを解析
            T jsonData = JsonConvert.DeserializeObject<T>(responseData);
            action(jsonData);
        }
    }
として、文字列をT型でデシリアイズして、それを引数にaction()を呼び出しています。
action()は引数がT型のラムダ式を引数に持つ式をコンストラクタで受け取ってます。
リクエストの呼び出し
        private void GetMe()
        {
            oauth.target = new JsonResult<GooglePlusData.Person>(GetPeople);
            oauth.GetPeople("me");
        }

        private void GetPeople(GooglePlusData.Person person)
        {
            //元のスレッドでメイン画面に遷移
            this.Dispatcher.BeginInvoke(() => NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative)));
        }
って感じでOKです。
GetPeple()はUrlを作成して、GETしています。

これでJsonResultの生成時に型情報と受け取りの実装を渡します。
総括
一瞬、OAuthを直接行う部分のインスタンス化を行う時にT型を使おうとしたのですが、
アクセストークンをやり取りするのがだるかったのでこうしています。
※おそらく後で分散ストレージを使うので、そうしなくても良かったかな?とも思ってます。
こうしておくことで多分他のOAuthを作りたい感じになった時に楽になるかな。。。と勝手に思ってます。

ここに行くまでブヒーって感じでした。
C#の知識が乏しい状況での実装なので、本当にこれでいいのかも不明です。


JavaScript辺りのゆるふわな感じと、Javaの静的な感じが実現できていて素晴らしいなぁ。
結論としては、、、λカワイイ。。。

0 件のコメント: