4

バイナリ シリアル化を使用して .NET 2.0 Remoting 経由で通信するクライアントとサーバー アプリケーションがあります。

データ転送オブジェクトのインターフェイスと実装クラスの 1 つに小さな変更が加えられました。文字列フィールドの配列が追加されました。

新しいバージョンのサーバー アプリケーションを再デプロイする場合、古いクライアントは引き続き動作しますか?

インターフェイスと直接実装から何も削除されていないため、そうなると思いますが、よくわかりません。

おそらく別の質問に要約されます-入力バイナリストリームでデータを見つけることができないフィールドをnullに初期化することで、このような状況を処理するのに「十分に賢い」バイナリデシリアライザーですか、それとも壊れて例外をスローするつもりですか?

4

2 に答える 2

4

新しいプロパティに属性を追加できます: OptionalField. この属性がないと、デシリアライザーはシリアル化されたデータを更新された定義に戻すことができません。この属性は、デシリアライザーが「不足している」データを適切に処理できるようにするためのものです。

新しいプロパティのデフォルト値を設定する場合、適切なデータが逆シリアル化されていない場合は、IDeserializationCallbackインターフェイスを実装し、デフォルト値があれば、結果のメソッドに設定します。

于 2010-08-20T01:20:41.940 に答える
1

おそらく例外がスローされる可能性があります。継承することで独自ISerializableのシリアライザーを実装し、独自のメソッドを使用してバージョン管理を実装することができGetObjectDataます...これにより、シリアル化されるデータをより厳密に制御できます。 ..ここに例があります

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class MyFooBar : ISerializable{
    private float _fVersion = 1.0;
    public MyFooBar(SerializationInfo info, StreamingContext context) {
         this._fVersion = info.GetSingle("FooBarVersionID");
         if (this._fVersion == 1.0F) bOk = this.HandleVersionOnePtZero(info, context);
         if (!bOk) throw new SerializationException(string.Format("MyFooBar: Could not handle this version {0}.", this._fVersion.ToString()));
    }
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
   public void GetObjectData(SerializationInfo info, StreamingContext context) {
       info.AddValue("FooBarVersionID", this._fVersion);
       if (this._fVersion == 1.0F) {
          // Bool's...
          info.AddValue("FooBarBool", FooBarBool);
          // etc... for Version 1.0
       }
       if (this._fVersion == 1.1F){
          // etc... for Version 1.0
       }
   }
}

以下に示すように、シリアル化/逆シリアル化するときに、このコンテキストで MyFooBar を使用します。

public bool Deserialize(string sFileName) {
            bool bSuccessful = false;
            //
            if (!System.IO.File.Exists(sFileName)) return false;
            fuBar = new MyFooBar();
            //
            try {
                using (FileStream fStream = new FileStream(sFileName, FileMode.Open)) {
                    try {
                        BinaryFormatter bf = new BinaryFormatter();
                        fuBar = (MyFooBar)bf.Deserialize(fStream);
                        bSuccessful = true;
                    } catch (System.Runtime.Serialization.SerializationException sEx) {
System.Diagnostics.Debug.WriteLine(string.Format("SERIALIZATION EXCEPTION> DETAILS ARE {0}", sEx.ToString()));
                        bSuccessful = false;
                    }
                }
            } catch (System.IO.IOException ioEx) {
                System.Diagnostics.Debug.WriteLine(string.Format("IO EXCEPTION> DETAILS ARE {0}", ioEx.ToString()));
                bSuccessful = false;
            }
            return (bSuccessful == true);
        }

2.0 以降では、これを行うためのより適切な方法がありますが、私はこの方法を好みます。

于 2010-08-20T01:00:47.130 に答える