Soul Reaver
Soul Reaver

Reputation: 2092

Deserialization of changed class

I am working on a program, where I save it's project files by serializing Project class. Because I am still working on it, some classes, that are part of Project class, do change from time to time (e.g. class got new property). It makes "simple" deserialization impossible.

Is there any way to solve it ? I mean, without writng custom serializer ? (which probably is something high above my level for now)

Just in case, I am using BinaryFormatter.

Upvotes: 1

Views: 6790

Answers (3)

Fischermaen
Fischermaen

Reputation: 12458

I hope I understood your problem correctly. You have a class serialized to a file which you have since changed in the program (e.g you have added another property). Now you want to deserialize this class from the file. This is not a problem as long as you have only added new properties. They will be ignored by the deserializer. It creates a new instance of your class (that is the reason why serializable classes have to have a default constructor) and tries to fill the properties it finds in the stream to derserialize. If you change a property's type or remove a property, you won't be able to deserialize the original file.

One workaround for removing properties is to keep them in the class, but just stop using them in the rest of the program. A workaround for properties that have been changed to a different type could look something like this:

[Serializable]
public class MyClass
{
     int? newProperty;
     [XmlElement("Property")]
     public string OldProperty 
     {
         get { return string.Empty; }
         set 
         { 
             if (!newProperty.HasValue)
             {
                  int temp;
                  if (int.TryParse(value, out temp))
                  {
                       newProperty.Value = temp;
                  }
             }
         }
     }

     public int NewProperty
     {
         get { return newPropery.HasValue ? newProperty.Value : 0; }
         set { newProperty.Value = value; }
     }
} 

Upvotes: 4

Soul Reaver
Soul Reaver

Reputation: 2092

With help from Merlyn Morgan-Graham's comments I've found solution, that will work for me.

Versioning described in Version Tolerant Serialization is really good idea, but when I use only [Serializable] attribute.

I forgot to write (my mistake), that I am using ISerializable interface. I've found, that in deserialization constructor SerializationInfo object has MemberCount property, which solves my problem if I only add new properties/members from time to time. With this information, new members/properties, that can't be deserialized from older file, can be set to default or maybe I can use some prompt form.

Other way here would be using something like assembly version in deserialization, as a first deserialized member. This can solve deserialization problems with more complex class changes.

Either way, I agree with Merylin - "if you can't script something, you shouldn't be building it". ;)

Upvotes: 1

Samuel Slade
Samuel Slade

Reputation: 8613

From my experience, I've found using BinaryFormatter for serialization/de-serialization of data types that are going to change a really bad idea. If something changes in your data type, from what I know the BinaryFormatter will fail in the process.

To overcome this issue in the data types I was using, I had to write my own serializer, which wasn't actually that much of a major task. You can use the BinaryReader and BinaryWriter classes to read and write the data in and out of your type. That way you can control the data you are expecting and handle any missing data either by adding default values, skipping the property altogether, or throwing some form of Exception to signify corrupt data. Refer to the MSDN article links above for more information.

Upvotes: 1

Related Questions