参考链接: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.datacontractserializer(DataContractSerializer-微软官方文档) https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer(XmlSerializer-微软官方文档) https://peterdaugaardrasmussen.com/2017/09/20/differences-between-datacontractserializer-and-xmlserializer/(C# - DataContractSerializer 和 XmlSerializer 之间的区别) https://stackoverflow.com/questions/5010191/using-datacontractserializer-to-serialize-but-cant-deserialize-back(DataContractSerializer使用参考) https://stackoverflow.com/questions/45443167/cant-deserilize-derived-class-but-it-works-if-its-in-a-list-or-a-dictionary-a/45443874#45443874(DataContractSerializer序列化自定义类型(未知类型)) https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.netdatacontractserializer(NetDataContractSerializer-微软官方文档)

帮助类

需要引用 System.Runtime.Serialization;

  1. using System;
  2. using System.IO;
  3. using System.Runtime.Serialization;
  4. /// <summary>
  5. /// XML序列化公共处理类
  6. /// </summary>
  7. public class DataContractSerializerHelper
  8. {
  9. /// <summary>
  10. /// 序列化
  11. /// </summary>
  12. /// <param name="obj">对象</param>
  13. /// <param name="types">对象包含的类型</param>
  14. /// <returns>xml字符串</returns>
  15. public static string XmlSerialize(object obj, Type[] types = null)
  16. {
  17. using (MemoryStream stream = new MemoryStream())
  18. {
  19. using (StreamReader read = new StreamReader(stream))
  20. {
  21. DataContractSerializer serializer = new DataContractSerializer(obj.GetType(), types);
  22. serializer.WriteObject(stream, obj);
  23. stream.Seek(0, SeekOrigin.Begin);
  24. return read.ReadToEnd();
  25. }
  26. }
  27. }
  28. /// <summary>
  29. /// 反序列化
  30. /// </summary>
  31. /// <param name="xml">xml字符串</param>
  32. /// <param name="type">对象类型</param>
  33. /// <param name="types">对象包含的类型</param>
  34. /// <returns>对象</returns>
  35. public static object DESerializer(string xml, Type type, Type[] types = null)
  36. {
  37. using (MemoryStream stream = new MemoryStream())
  38. {
  39. using (StreamWriter writer = new StreamWriter(stream))
  40. {
  41. writer.Write(xml);
  42. writer.Flush();
  43. stream.Seek(0, SeekOrigin.Begin);
  44. DataContractSerializer serializer = new DataContractSerializer(type, types);
  45. return serializer.ReadObject(stream);
  46. }
  47. }
  48. }
  49. }

使用方式

  1. namespace Tests
  2. {
  3. public class Test
  4. {
  5. public string Name;
  6. public int Min;
  7. public int Max;
  8. }
  9. }
  10. Tests.Test test = new Tests.Test() { Name = "test", Min = 10, Max = 100 };
  11. string xml = DataContractSerializerHelper.XmlSerialize(test);
  12. Tests.Test test2 = DataContractSerializerHelper.DESerializer(xml, test.GetType()) as Tests.Test;

DataContractSerializer:使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档。 此类不能被继承。(官方介绍)

对比DataContractSerializer和XmlSerializer(未完,待补充)

XmlSerializer:

  • 只序列化公有属性/字段
  • 可以通过[XmlIgnore]特性标识忽略序列化
  • 序列化的类型需要提供无参构造函数
  • 无法序列化实现IDictionary接口的类型(键值对)
  • 反序列化有object的未知类型(自定义类),会变成System.Xml.XmlNode,可以通过反序列化时添加指定类型避免。XmlSerializer的构造函数 XmlSerializer(Type type, Type[] extraTypes);

DataContractSerializer:

  • 对序列化顺序有要求(详细看后面的介绍)
  • 可以序列化没有无参构造函数的类,通过在类上添加[DataContract]特性
  • 可以序列化 私有、受保护、内部、受保护内部或公共 的属性和字段,通过添加[DataMember]特性

DataContractSerializer对于序列化的顺序的要求

示例:

  1. namespace Tests
  2. {
  3. public class Test
  4. {
  5. public string Name;
  6. public int Min;
  7. public int Max;
  8. }
  9. }
  10. Tests.Test test = new Tests.Test() { Name = "test", Min = 10, Max = 100 };

序列化出来的xml为
<Test xmlns="http://schemas.datacontract.org/2004/07/Tests" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Max>100</Max><Min>10</Min><Name>test</Name></Test>

如果将XML里面的字段/属性顺序更换改成这样,然后反序列化,注意红色部分为修改的顺序。
<Test xmlns="http://schemas.datacontract.org/2004/07/Tests" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Name>test</Name><Min>10</Min><Max>100</Max></Test>

反序列化时Name="test",Min=0,Max=0。Min和Max的值没有被赋值,反序列化时也不会报错。

DataContractSerializer添加的特性(待补充)

补充

对于不想/不愿意处理未知类型(自定义)的Type,可以使用NetDataContractSerializer.
NetDataContractSerializer仅限Framework框架可用。
可用版本
.NET Framework 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8
Xamarin.iOS 10.8
Xamarin.Mac 3.0

对于想在.Net Core中使用的,可以参考这些链接
https://stackoverflow.com/questions/53002135/how-to-deserialize-netdatacontractserializer-data-in-net-core(如何反序列化 .NET Core 中的 NetDataContractSerializer 数据?)
https://github.com/dotnet/runtime/issues/27763(这里讨论了为什么不在.NET Core中实现)
https://github.com/dmitrykolchev/NetDataContractSerializer(第三方在.NET Core中实现NetDataContractSerializer

NetDataContractSerializer在一个重要方面与DataContractSerializer不同:NetDataContractSerializer在序列化的 XML 中包含 CLR 类型信息,而DataContractSerializer不包含。因此,只有在序列化和反序列化端共享相同的 CLR 类型时,才能使用NetDataContractSerializer 。

NetDataContractSerializer使用方式和DataContractSerializer类似,上面的帮助类只需要,将DataContractSerializer修改成NetDataContractSerializer,然后去除参数里的Type