I have this class
[Serializable]
public class myClass() : ISerializable
{
public int a;
public int b;
public int c;
public void GetObjectData(SerializationInfo info,
StreamingContext context)
{
// Some code
}
public myClass(SerializationInfo info,
StreamingContext context)
{
// Some code
}
}
I have hundreds of these object in my database. I am now ready to publish a new version of my app where the class has morphed to
[Serializable]
public class myClass() : ISerializable
{
public int a;
public string b;
public int c;
public bool d;
public void GetObjectData(SerializationInfo info,
StreamingContext context)
{
// Some code
}
public myClass(SerializationInfo info,
StreamingContext context)
{
// Some code
}
}
How would one deserialize an object serialized based on the first version with the de-serialization constructor of the second.
Are there also strategies for future version proofing my second version of the class?
For serializing the object, we call the writeObject() method of ObjectOutputStream class, and for deserialization we call the readObject() method of ObjectInputStream class. We must have to implement the Serializable interface for serializing the object.
Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.
As the name suggests, deserialization in C# is the reverse process of serialization. It is the process of getting back the serialized object so that it can be loaded into memory. It resurrects the state of the object by setting properties, fields etc.
Serialization is the process of converting the state of an object into a form that can be persisted or transported. The complement of serialization is deserialization, which converts a stream into an object. Together, these processes allow data to be stored and transferred. .
Without preparation on your part, you may need to resort to a hack: when your public myClass
deserialization constructor gets the value of bool d
, enclose the code in try
/catch
, and set d
to its default value when you catch an exception.
In the future, add an int
value "__ver"
(or any other name that does not collide with arguments that you pass to info.AddValue
), and set it to a constant that you maintain in your class to indicate compatible and incompatible changes in serialization:
public class myClass : ISerializable {
private const int __ver = 4;
public int a;
public string b;
public int c;
public bool d;
public void GetObjectData(SerializationInfo info,
StreamingContext context) {
info.AddValue("__ver", ver);
info.AddValue("a", a);
// and so on
}
public myClass(SerializationInfo info,
StreamingContext context) {
switch(info.GetInt32("__ver")) {
case 3:
// Deserialize prior version
break;
case 4:
// Deserialize current version
break;
}
}
}
Serializable classes are great for passing them around through the same version of software, but you hit this issue quickly when using it for persistence. If you are going to store objects as BLOBs, then maybe use something like protobuf-net which allows serialization versioning by allowing for optional fields.
Given your current predicament all you can do to get it to work imediatly is put a try catch around the new fields, and then default them if they are not there:
protected myClass(SerializationInfo info, StreamingContext context)
{
c = info.GetInt32("Value_C");
try
{
b = info.GetBoolean("Value_B");
}
catch (SerializationException)
{
b = true;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With