参考链接: 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;
using System;
using System.IO;
using System.Runtime.Serialization;
/// <summary>
/// XML序列化公共处理类
/// </summary>
public class DataContractSerializerHelper
{
/// <summary>
/// 序列化
/// </summary>
/// <param name="obj">对象</param>
/// <param name="types">对象包含的类型</param>
/// <returns>xml字符串</returns>
public static string XmlSerialize(object obj, Type[] types = null)
{
using (MemoryStream stream = new MemoryStream())
{
using (StreamReader read = new StreamReader(stream))
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType(), types);
serializer.WriteObject(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
return read.ReadToEnd();
}
}
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="xml">xml字符串</param>
/// <param name="type">对象类型</param>
/// <param name="types">对象包含的类型</param>
/// <returns>对象</returns>
public static object DESerializer(string xml, Type type, Type[] types = null)
{
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(xml);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
DataContractSerializer serializer = new DataContractSerializer(type, types);
return serializer.ReadObject(stream);
}
}
}
}
使用方式
namespace Tests
{
public class Test
{
public string Name;
public int Min;
public int Max;
}
}
Tests.Test test = new Tests.Test() { Name = "test", Min = 10, Max = 100 };
string xml = DataContractSerializerHelper.XmlSerialize(test);
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对于序列化的顺序的要求
示例:
namespace Tests
{
public class Test
{
public string Name;
public int Min;
public int Max;
}
}
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
。