在C#的XML序列化场景中,DataContractSerializer和XmlSerializer是微软提供的两种核心序列化工具,二者都能实现对象与XML数据的相互转换,但设计目标和实现逻辑存在诸多差异,适配不同的开发需求。
核心设计目标差异
XmlSerializer是早期推出的XML序列化工具,设计目标是完全遵循XML规范,尽可能保留XML的结构化特性,支持精细控制XML元素的命名、命名空间、属性映射等细节,适合需要和其他系统做严格XML格式对接的场景。
DataContractSerializer是WCF框架配套推出的序列化工具,设计目标是优先保证序列化的兼容性和性能,默认采用宽松的序列化规则,不需要对象完全匹配XML结构也能完成序列化,更适合内部服务之间的数据传输场景。
序列化规则对比
默认序列化范围
XmlSerializer默认只序列化对象的公共属性和公共字段,私有成员不会被处理,同时不会序列化只读属性(没有setter的属性)。
DataContractSerializer默认只序列化标记了DataMember特性的成员,无论成员是公共还是私有,只要标记了特性就会被序列化,同时支持只读成员的序列化。
构造函数要求
使用XmlSerializer序列化时,对象必须有无参公共构造函数,否则会直接抛出异常。
DataContractSerializer对构造函数没有强制要求,即使对象没有无参构造函数,也能正常完成序列化和反序列化操作。
特性使用差异
二者使用的控制序列化的特性完全不同,不能混用:
- XmlSerializer使用
System.Xml.Serialization命名空间下的特性,比如XmlRoot、XmlElement、XmlAttribute、XmlIgnore等,用来控制XML元素、属性、命名空间等细节。 - DataContractSerializer使用
System.Runtime.Serialization命名空间下的特性,核心特性是DataContract(标记类可序列化)和DataMember(标记成员需要序列化),控制能力相对简单,主要用来指定成员顺序、名称。
代码示例对比
定义测试类
首先定义一个同时适配两种序列化器的测试类:
using System;
using System.Runtime.Serialization;
using System.Xml.Serialization;
// XmlSerializer需要的无参构造函数
// DataContractSerializer需要的DataContract特性
[DataContract(Name = "User", Namespace = "http://example.org")]
[XmlRoot("User")]
public class User
{
// XmlSerializer默认序列化公共属性
// DataContractSerializer需要DataMember特性
[DataMember(Name = "UserId", Order = 1)]
[XmlElement("UserId")]
public int Id { get; set; }
[DataMember(Name = "UserName", Order = 2)]
[XmlElement("UserName")]
public string Name { get; set; }
// 私有字段,XmlSerializer不会序列化,DataContractSerializer标记后才会序列化
[DataMember(Name = "UserAge", Order = 3)]
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
// 标记XmlIgnore,XmlSerializer会忽略该属性
// 没有标记DataMember,DataContractSerializer也会忽略
[XmlIgnore]
public string Temp { get; set; }
// 无参构造函数,满足XmlSerializer要求
public User() { }
public User(int id, string name, int age)
{
Id = id;
Name = name;
this.age = age;
}
}
XmlSerializer序列化示例
using System;
using System.IO;
using System.Xml.Serialization;
class Program
{
static void Main()
{
User user = new User(1, "张三", 20);
user.Temp = "临时数据";
// 创建XmlSerializer实例,指定要序列化的类型
XmlSerializer xmlSerializer = new XmlSerializer(typeof(User));
using (StringWriter writer = new StringWriter())
{
xmlSerializer.Serialize(writer, user);
string xmlResult = writer.ToString();
Console.WriteLine("XmlSerializer序列化结果:");
Console.WriteLine(xmlResult);
}
// 反序列化
string xmlContent = "<User><UserId>1</UserId><UserName>张三</UserName><Age>20</Age></User>";
using (StringReader reader = new StringReader(xmlContent))
{
User deserializedUser = (User)xmlSerializer.Deserialize(reader);
Console.WriteLine($"反序列化结果:Id={deserializedUser.Id}, Name={deserializedUser.Name}, Age={deserializedUser.Age}, Temp={deserializedUser.Temp}");
}
}
}
DataContractSerializer序列化示例
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
class Program
{
static void Main()
{
User user = new User(1, "张三", 20);
user.Temp = "临时数据";
// 创建DataContractSerializer实例,指定要序列化的类型
DataContractSerializer dcSerializer = new DataContractSerializer(typeof(User));
using (MemoryStream stream = new MemoryStream())
{
dcSerializer.WriteObject(stream, user);
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream))
{
string xmlResult = reader.ReadToEnd();
Console.WriteLine("DataContractSerializer序列化结果:");
Console.WriteLine(xmlResult);
}
}
// 反序列化
string xmlContent = "<User xmlns="http://example.org"><UserId>1</UserId><UserName>张三</UserName><UserAge>20</UserAge></User>";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xmlContent);
using (MemoryStream stream = new MemoryStream(bytes))
{
User deserializedUser = (User)dcSerializer.ReadObject(stream);
Console.WriteLine($"反序列化结果:Id={deserializedUser.Id}, Name={deserializedUser.Name}, Age={deserializedUser.Age}, Temp={deserializedUser.Temp}");
}
}
}
其他差异汇总
| 对比维度 | XmlSerializer | DataContractSerializer |
|---|---|---|
| 性能 | 首次序列化需要生成临时程序集,性能稍低 | 内部做了更多优化,性能相对更高 |
| 兼容性 | 严格遵循XML规范,和其他XML系统兼容性好 | 序列化规则宽松,不同版本间兼容性更好 |
| 未知元素处理 | 遇到未定义的XML元素会抛出异常 | 默认忽略未知元素,不会报错 |
| 循环引用支持 | 不支持,序列化循环引用对象会抛出异常 | 支持,通过DataContract特性的IsReference属性开启 |
选型建议
如果是需要和第三方系统做严格的XML格式对接,要求完全控制XML的结构、命名空间、属性等细节,优先选择XmlSerializer。
如果是内部服务之间的数据传输,或者需要更高的性能、更好的版本兼容性,不需要严格遵循XML规范,优先选择DataContractSerializer。
DataContractSerializerXmlSerializerC#_xml序列化序列化差异修改时间:2026-06-21 15:39:45