从较旧版本的对象反序列化较新版本的对象

时间:2013-10-31 23:20:52

标签: c# serialization deserialization binaryformatter

假设我有这门课程:

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

当应用程序关闭时,此类将获得序列化,并在下次运行时进行反序列化。

然后,我构建了它并发布了应用程序,现在课程已经改变了:

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

是否有办法在反序列化时将属性设置为默认值,以防在旧的序列化对象中找不到它?

我想到的一种方法是保留类的旧版本,然后检查已序列化的版本然后循环旧对象的属性并在新对象中设置它们,但这对我来说是没有意义的,任何其他解决方案这有道理吗?

2 个答案:

答案 0 :(得分:4)

您可以使用属性

标记字段
[OptionalField()]

,如Version Tolerant Serialization

中所述

该课程将如下所示:

[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;
    }
}

答案 1 :(得分:2)

我要做的是将SomeInt基于字段具有默认值的字段。 IE。

public class SomeClass
{
    public SomeClass() { }

    int someInt = 10;

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

然后,如果未提供SomeInt值,则序列化程序反序列化对象时仍会设置默认值。

编辑:更新

使用XML序列化程序添加了示例应用程序。现在切换类类型只需取消注释第2行中的#define serialize语句。

//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
}