Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing a newer version of an object from an older version of the object

Suppose I had this class:

[Serializable]
public class SomeClass 
{
   public SomeClass() {//init}
   public string SomeString {get;set;}
}

This class gets Serialized when the application closes, and gets deserialized on the next run.

Then, I built it and released the application, and now the class has changed:

[Serializable]
public class SomeClass
{
   public SomeClass() {//init}
   public string SomeString {get;set;}
   public int SomeInt {get;set;}
}

Is there a way to set a property to its default on deserialization in case its not found in the old serialized object?

One way I thought about is keeping the old version of the class, then check the version that was serialized then looping properties of the old object and setting them in the new object, but this is non sense to me, any other solution that makes sense?

like image 974
FPGA Avatar asked Oct 31 '13 23:10

FPGA


2 Answers

You can mark fields with the attribute

[OptionalField()]

as explained in Version Tolerant Serialization

The class would then look like this:

[Serializable()]
public class SomeClass
{
    public SomeClass() {//init}
    public string SomeString { get; set; }

    [OptionalField(VersionAdded = 2)]
    public int SomeInt { get; set; }


    [OnDeserialized()]
    private void SetValuesOnDeserialized(StreamingContext context)
    {
        this.SomeInt = 10;
    }
}
like image 191
Markus Safar Avatar answered Sep 21 '22 23:09

Markus Safar


What i would do is base the SomeInt on a field where the field has a default value. IE.

public class SomeClass
{
    public SomeClass() { }

    int someInt = 10;

    public string SomeString { get; set; }
    public int SomeInt
    {
        get { return someInt; }
        set { someInt = value; }
    }
}

Then when the serializer deserializes the object if the SomeInt value is not provided the default value is still set.

EDIT: Update

Added a sample app using the XML serializer. Now to toggle the class type simply uncomment the #define serialize statement in row 2.

//uncomment for serialization
//#define serialize

using System;
using System.IO;
using System.Xml.Serialization;

namespace TestSerializer
{
    class Program
    {
        static void Main(string[] args)
        {

#if serialize

            SomeClass some = new SomeClass();
            some.SomeString = "abc";

            XmlSerializer serializer = new XmlSerializer(some.GetType());
            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, some);
                File.WriteAllText("D:\\test.xml", writer.ToString());
            }
#else
            XmlSerializer serializer = new XmlSerializer(typeof(SomeClass));
            using (StringReader reader = new StringReader(File.ReadAllText("D:\\test.xml")))
            {
                var o = serializer.Deserialize(reader) as SomeClass;
                if (o != null)
                    Console.WriteLine(o.SomeInt);
            }
            Console.ReadKey();
#endif
        }
    }



#if serialize

    [Serializable]
    public class SomeClass
    {
        public SomeClass() { }
        public string SomeString { get; set; }
    }
#else

    [Serializable]
    public class SomeClass
    {
        public SomeClass() { }
        private int someInt = 10;


        public string SomeString { get; set; }
        public int SomeInt
        {
            get { return someInt; }
            set { someInt = value; }
        }
    }
#endif
}
like image 23
Nico Avatar answered Sep 23 '22 23:09

Nico