2012年09月23日
川俣晶の縁側ソフトウェア技術雑記 total 5950 count

Windowsストア アプリのLoadState/SaveStateメソッドでオブジェクトを扱う罠

Written By: 川俣 晶連絡先

「無駄に時間を食ったのでメモだ」

「なんだい?」

「Visual Studio 2012でWindowsストアアプリのプロジェクトを作成すると、LoadState/SaveStateメソッドが生成される場合がある」

「見たことあるよ。何をするメソッド?」

「状態の保存と復帰だ。他のページに行ったり戻ったりする際に呼ばれる」

「何が問題なの?」

「この2つのメソッドには以下のような引数が渡される」

  • Dictionary<String, Object> pageState

「ディクショナリだね。これに値を登録すれば保存されるわけだね」

「その通りだ。だから以下のようなコードを書けば値が保存される」

  • pageState["B"] = "abc" + DateTime.Now.ToString();

「めでたしめでたしだね」

「ところが、文字列型をやめて自分で宣言したクラスのオブジェクトを渡すと、プロセスがサスペンドする際に例外で落ちる」

「なぜ?」

「最初なぜか分からなかった。文字列なら良くて他のオブジェクトはダメという理由が思い付かなかった」

「あ、DataContract属性とDataMember属性だ」

「最初から付いてるよ」

    [DataContract]

    public class A

    {

        [DataMember]

        public string a;

    }

「結局原因はなに?」

「SuspensionManagerに型を教えてやらないとシリアライズできない。たとえばAppクラスのコンストラクタに以下のようなコードを入れる」

  • SuspensionManager.KnownTypes.Add(typeof(A));

感想 §

「なぜこんなつまらない問題に引っかかったの?」

「最初山勘で文字列を入れたら動いたので、そんなものかと思って独自クラスを指定したら動かなかった。その時のエラーメッセージがあまり親切ではなく、違う問題を疑ってしまったからだ」

「問題はミスリードさせるようなメッセージか」

「もう1つ、問題がある」

「それはなんだい?」

「LoadState/SaveStateメソッドもSuspensionManagerも、WinRTの一部ではないのでドキュメントが足りない。F1で仕様が引けない」

「えっ? なんで?」

「ユーザープログラム内にソースが自動生成されるからさ」

「ドキュメントが無いのでは、どうすりゃいいのさ」

「ソースを読むのだよ。自プロジェクト内にあるからすぐ読める」

「ぎゃふん」