1

新しいオプション フィールドをクラスに追加すると、以前にシリアル化されたこのクラスのインスタンスは、シリアル化解除できなくなります。

BinaryFormatter を使用して MyClass のいくつかのインスタンスを保存したとします。

[Serializable]
public class MyClass
{
    public MyType A;
}

その後、MyClass の 2 回目のリビジョン:

[Serializable]
public class MyClass
{
    public MyType A;

    [OptionalField(VersionAdded = 2)]
    public MyType NewField;
}

古いオブジェクトはデシリアライズできなくなりました。それらを逆シリアル化しようとしたときに取得したスタック トレースは次のとおりです (プロファイルは .NET 4.0 です)。

System.ArgumentNullException: Value cannot be null.    
Parameter name: type    
   at System.Reflection.Assembly.GetAssembly(Type type)    
   at System.Runtime.Serialization.Formatters.Binary.BinaryConverter.GetParserBinaryTypeInfo(Type type, Object& typeInformation)    
   at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, Type objectType, String[] memberNames, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo)    
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMap(BinaryObjectWithMap record)    
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()    
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)    
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)    
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage)    
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck)

インターネットまたは同様のスタック トレースでこのスタック トレースを見つけることができません。Mono でソフトウェアを実行すると、同じファイルを読み取ることができることに注意してください ;-) 。このため、この問題は .NET のバグに関連している可能性があると思います。

4

1 に答える 1

0

次のクラス タイプがあるとします。

[Serializable]
public class MyClass
{
    public MyType A;
}

[Serializable]
public class MyType
{
    public string Name { get; set; }
}

MyClass のインスタンスをファイルにシリアル化しましょう。

using (var stream = new FileStream(@"c:\temp\test.dat", FileMode.Create, FileAccess.Write))
{
    var formatter = new BinaryFormatter();
    formatter.Serialize(stream, new MyClass { A = new MyType { Name = "Christophe" } });
}

次に、これをデシリアライズして MyClass のインスタンスに戻します。

using (var stream = new FileStream(@"c:\temp\test.dat", FileMode.Open, FileAccess.Read))
{
    var formatter = new BinaryFormatter();
    var myInstance = (MyClass) formatter.Deserialize(stream);
}

問題ない。すべて正常に動作します。MyClass 型に新しいフィールドを追加しましょう。代わりにプロパティを使用することをお勧めします。

[Serializable]
public class MyClass
{
    public MyType A;

    [OptionalField]
    public MyType B;
}

デシリアライゼーションは引き続き正常に機能します。私の場合、B の欠損データは無視され、null に設定されます。

于 2012-06-05T17:54:53.547 に答える