0

私はAS3Air開発を行い、SQLiteを使用してセッション間にオブジェクトを保存します。これは、AS3開発者ガイドおよびAS3SDKリファレンスに詳しく記載されています。

データベースに格納されているクラスはIExternalizableを実装しているため、BLOBを使用してインスタンスを格納および復元できます。これはうまくいきますが、失敗した逆シリアル化に適切に対応する方法を見つけるのは困難です。この問題は、次の状況で発生します。

  1. シリアル化されたオブジェクト
  2. 保存されたオブジェクト
  3. クラスが変更され、プログラムが更新されました
  4. シリアル化されたデータは保存されたデータと一致しなくなりました

私の最初のアプローチは次のようなものです。

public class SampleClass implements IExternalizable
{
    public static const version:int = 1; //increments upon program update
    public var idata:int;

    public function readExternal(data:IDataInput):void{
        if(version != data.readInt()) //check for corrupted data
            throw new IOError();

        idata = data.readInt();
    }

    public function writeExternal(data:IDataOutput):void{
        data.writeInt(version);
        data.writeInt(idata);
    }
}

readExternalでエラーをスローすると、悲しいことにSQLStatement.execute()がひどく失敗し、try..catchは役に立ちません。

この問題に対処するための私の現在のアイデア:

  1. プログラムが更新されたときにデータベースからすべてのデータを消去します(痛い)
  2. クラスにフラグを追加して、誤った逆シリアル化を通知します
  3. SQLStatement.execute()がスローされたエラーに適切に反応するようにします

1と2私はやり方を知っていますが、どちらもきれいではありません。3(まだ?)の解決策が見つかりません

他のアイデアやノウハウを高く評価しています。

4

1 に答える 1

2

こんにちは、これは Adob​​e AIR 1.5 クックブック (9.13 Migrating Serialization Changes in ActionScript) に記載されています。寄稿者Greg Jastrab 氏は、次のコード サンプルのように、バージョンの変更に名前空間を使用することを提案しています。

public class WeatherData implements IExternalizable {
    namespace wd1_0 = "WD1.0";
    namespace wd1_1 = "WD1.1";

    protected var version:String;
    public var date:Date;
    public var low:Number;
    public var high:Number;

    public function WeatherData() {
        version = "WD1.1";
        date = new Date();
        low = high = 0;
    }
    public function readExternal(input:IDataInput):void {
        version = input.readUTF();
        var ns:Namespace = new Namespace(version);
        ns::parse(input);
    }
    public function writeExternal(output:IDataOutput):void {
        output.writeUTF(version);
        output.writeObject(date);
        output.writeFloat(low);
        output.writeFloat(high);
    }
    wd1_0 function parse(input:IDataInput):void {
        date = input.readObject() as Date;
        high = input.readFloat();
    }
    wd1_1 function parse(input:IDataInput):void {
        date = input.readObject() as Date;
        low = input.readFloat();
        high = input.readFloat();
    }
}

私はこのソリューションを使用しましたが、約束どおりに機能します:)そして、以下は将来のバージョンで新しいメンバーを追加するための「アルゴリズム」です

  1. 新しい変数を追加
  2. writeExternal を変更してシリアライゼーションに含める
  3. コンストラクターでバージョン文字列をインクリメントする
  4. 新しいバージョンの新しい名前空間を追加
  5. 新しい名前空間をスコープとする解析関数を追加し、変更された writeExternal に一致するように readExternal を実装する

よろしくお願いします

于 2013-01-03T09:09:16.270 に答える