ISerializableとの後方互換性
-
26-09-2019 - |
質問
うれしい仕事をされていたアプリケーションを用いたbinaryFormatterにserialize用データfilestreamえという名前のファイル"データです。oldformat") なoptimizazionのクラスでしか受け入れられない属性
<serializable()>public MainClass
.......
end class
の直列化コード
dim b as new binaryformatter
b.serialize(mystream,mymainclass)
るための最適化に直列化/直列化復元処理までのクラスの実施にISerializableタで書いていただき最適な直列化ルーチン
<serializable()>public MainClass
implements ISerializable
.......
end class
最適化の作品も、"ちびまる子ちゃんとおかし私はそれreatriveのデータ内のファイルの後方に対応しています。
できるかということですかね??
Pierluigi
解決
stmax 優れた応答しい実践できるようにする SerializationEntry.GetEnumerator()
の代わりに try/catch
.この方法は、クリーンで大きくなります。
public MainClass(SerializationInfo info, StreamingContext context) {
int version = 0;
foreach (SerializationEntry s in info)
{
if (s.Name == "version")
{
version = (int)s.Value;
break;
}
}
switch (version) {
case 0:
// deserialize "old format"
break;
case 1:
// deserialize "new format, version 1"
break;
default:
throw new NotSupportedException("version " + version + " is not supported.");
}
}
私は好きでLINQ版。FirstOrDefault()がSerializationInfoな実施IEnumerable-、妙に十分なされているとは思いませんが、でも実は、旧IEnumerableインタフェース。
他のヒント
はすでにISerializableインターフェイスを実装してきたことから、あなたはおそらくすでに必要なコンストラクタを追加しました
public MainClass(SerializationInfo info, StreamingContext context) {}
あなたはシリアル化されたファイルからデータを取得するために、コンストラクタに渡されたインフォオブジェクトを使用することができます。 の(何ISerializableが実装されていない、すなわち)デフォルトで、フィールド名は、シリアル化中に識別子として使用されています。古いクラスは「int型のx」フィールドを持っていた場合ので、あなたは、この使用してデシリアライズすることができます:の
this.x = info.GetInt32("x");
新しいバージョンのために、私は通常、このように、直列化の際に「バージョン」のエントリを追加します
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("version", 1);
info.AddValue("othervalues", ...);
}
このバージョンのエントリをチェックし、それに応じてデシリアライズすることができ、逆シリアル化中に:
public MainClass(SerializationInfo info, StreamingContext context) {
int version;
try {
version = info.GetInt32("version");
}
catch {
version = 0;
}
switch (version) {
case 0:
// deserialize "old format"
break;
case 1:
// deserialize "new format, version 1"
break;
default:
throw new NotSupportedException("version " + version + " is not supported.");
}
}
私はコードは、タイプミスが含まれている可能性がコンパイルされていない。
に役立ちます願っています。
ちょうどあなたがこれまで行ってきた、同じことをしてみてください。
BinaryFormatter b = new BinaryFormatter();
MainClass a = b.DeSerialize(mystream) as MainClass;
実装ISerializableがあなたの元のクラスを変更していない、基本的にはあなただけのいくつかのメソッドを追加しました。
あなたのオブジェクトを直列化(これはあまりにも多くのオーバーヘッドを追加しないでください)、追加のバージョンフィールドを追加します。次に、あなたのGetObjectDataメソッド、最初のバージョンのフィールドを取得し、これは(SerializationExceptionを引くことで)存在するか否かに基づいてしようとして古い方法や新しい方法をデシリアライズします。あなただけのすべてのフィールドの取得...を呼び出すことができるはずですので、古い方法は、ちょうどすべてのデータをシリアライズしているでしょう。
あなたの前のコードは動作するはずです。あなたは例外を得るのですか? 新しいコンストラクタを使用してみます:
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)