在C#中,如何将XML从较旧的对象反序列化为更新的对象并忽略缺少的xml元素?

Mik*_*ebb 14 c# xml-serialization defaults

我有一个自定义设置文件,我使用一个序列化/反序列化XmlSerializer.我的对象定义中没有定义架构且没有序列化标签,只是直接对象序列化(尽管如果需要我会添加它们).

我的问题是我需要向对象添加数据成员.如果我这样做,我知道旧的设置文件不会反序列化.

有没有办法为添加的成员指定默认值,或者如果XML中缺少这些默认值,可以采用一些简单的方法来忽略它们?

Sur*_*mra 7

来自MSDN

最佳实践要确保正确的版本控制行为,请在从版本到版本修改类型时遵循以下规则:

  • 添加新的序列化字段时,应用OptionalFieldAttribute属性.

  • 从字段中删除NonSerializedAttribute属性(在以前的版本中不可序列化)时,应用OptionalFieldAttribute属性.

  • 对于所有可选字段,请使用序列化回调设置有意义的默认值,除非可以接受0或null作为默认值.

我试图模拟你的情况,在新版本的类中有新成员名为Element2.我的新成员初始化为"这是新成员"这里是完全证明

Test1假设您使用一个Element1序列化了Root类的旧定义

使用Root Class的新定义进行序列化和反序列化时的Test2

要以任何方式回答您的问题以提供默认值,您应该使用"OptionalField"

using System;
using System.Runtime.Serialization;
using System.IO;

public class Test
{

  [Serializable]
  public class Root
  {
    [OptionalField(VersionAdded = 2)] // As recommended by Microsoft
    private string mElement2 = "This is new member";
    public String Element1 { get; set; }    
    public String Element2 { get { return mElement2; } set { mElement2 = value; } }
  }

  public static void Main(string[] s)
  {
    Console.WriteLine("Testing serialized with old definition of Root ");
    Console.WriteLine(" ");
    Test_When_Original_Object_Was_Serialized_With_One_Element();
    Console.WriteLine(" ");
    Console.WriteLine("Testing serialized with new definition of Root ");
    Console.WriteLine(" ");
    Test_When_Original_Object_Was_Serialized_With_Two_Element();
    Console.ReadLine();
  }

  private static void TestReadingObjects(string xml)
  {
    System.Xml.Serialization.XmlSerializer xmlSerializer =
    new System.Xml.Serialization.XmlSerializer(typeof(Root));


    System.IO.Stream stream = new MemoryStream();
    System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    Byte[] bytes = encoding.GetBytes(xml);
    stream.Write(bytes, 0, bytes.Length);
    stream.Position = 0;
    Root r = (Root)xmlSerializer.Deserialize(stream);

    Console.WriteLine(string.Format("Element 1 = {0}", r.Element1));

    Console.WriteLine(string.Format("Element 2 = {0}", r.Element2 == null ? "Null" : r.Element2));
  }
  private static void Test_When_Original_Object_Was_Serialized_With_One_Element()
  {
    TestReadingObjects(@"<Root>   <Element1>1</Element1>   </Root>");
  }

  private static void Test_When_Original_Object_Was_Serialized_With_Two_Element()
  {
    TestReadingObjects(@"<Root>   <Element1>1</Element1> <Element2>2</Element2>   </Root>");
  }
}
Run Code Online (Sandbox Code Playgroud)

//这是输出 在此输入图像描述


McK*_*Kay 5

它应该反序列化很好,它将只使用默认构造函数来初始化项目.所以它们将保持不变.