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

C# 从对象的旧版本反序列化对象的新版本,c#,serialization,deserialization,binaryformatter,C#,Serialization,Deserialization,Binaryformatter,假设我上过这门课: [Serializable] public class SomeClass { public SomeClass() {//init} public string SomeString {get;set;} } 该类在应用程序关闭时序列化,并在下次运行时反序列化 然后,我构建了它并发布了应用程序,现在类发生了变化: [Serializable] public class SomeClass { public SomeClass() {//init}

假设我上过这门课:

[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;}
}
如果在旧的序列化对象中找不到属性,是否有方法将属性设置为反序列化时的默认值


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

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

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
}

可以使用该属性标记字段

[OptionalField()]
如中所述

然后,该类将如下所示:

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

什么序列化程序?有一些接口/属性可以用来修改对象[反]序列化的方式,但这取决于哪个库。@BradChristie我使用的是
BinaryFormatter
看看如何使用自定义的let me test,我不认为它像反序列化那样简单,但某些int值是0而不是10!我尝试了多个类型,反序列化后得到的是该类型的默认值,而不是字段中指定的值。我刚刚添加了一个代码示例,该示例适用于您的情况,您需要使用OnDeserialized()属性来满足您的需要。在我的回答中,我没有看到您使用的是BinaryFormatter。这对二进制格式化程序不起作用。但是如果没有
[ondesellized()]
,就无法指定默认值,对吗?我尝试设置backing字段值,但它给出的是0而不是10,但在
[OnDeserialized()]
中效果很好,据我所知,只有一种方法。您可以实现,它强制您实现方法GetObjectData(在序列化过程中使用),并且您还需要实现一个附加构造函数,其中包含两个参数(SerializationInfo、StreamingContext context),这两个参数将在反序列化过程中使用。您也可以在那里设置字段/属性的值,但我认为这相当复杂。
SetValuesOnDeserialized
是否总是被调用?因此,是否总是覆盖此.SomeInt?因此,在反序列化之后,它始终是相同的值,无论序列化时的值是什么?@mikedklerk实际上是的,但它是在对象填充流中的值之前调用的。因此,只有当流中的字段有一个值时,默认值10才会被覆盖。@MarkusSafar太好了,谢谢!这对我来说很清楚。也许我应该使用
OnDeserialized
,而不是为>10个属性创建备份字段:D。