Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strategy for deserializing a class that has changed in .NET

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?

like image 279
Matt Avatar asked Apr 19 '12 22:04

Matt


People also ask

Which method is used for deserialization?

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.

What is the difference between serialization and deserialization in C#?

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.

What is deserializer in C#?

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.

What is serialization in .NET with example?

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. .


2 Answers

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;
        }
    }
}
like image 90
Sergey Kalinichenko Avatar answered Oct 15 '22 03:10

Sergey Kalinichenko


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;
    }
}
like image 40
Pete Davis Avatar answered Oct 15 '22 05:10

Pete Davis