在WCF(Windows Communication Foundation)体系里,序列化器承担着将内存对象转为XML消息以及反向还原的核心职责。DataContractSerializer是框架默认且推荐使用的XML序列化器,它基于显式声明的“数据契约”工作,只有被标记的成员才会进入消息体。理解它的配置方式,是构建稳定服务接口的基础。

DataContractSerializer的基础配置与特性使用
要让DataContractSerializer生效,第一步是在业务类上添加DataContract特性,并在需要序列化的属性或字段上添加DataMember特性。这与早期ASP.NET Web Service依赖Serializable或公共属性自动序列化的逻辑完全不同。WCF要求开发者明确告知运行时哪些数据属于契约的一部分,从而避免意外泄露内部状态。
下面的示例展示了一个订单类的标准定义。其中OrderId和CustomerName被标记为数据成员,而内部计算的CacheKey因为没有DataMember,在序列化时会被忽略。通过Name和Order等参数,我们还能自定义节点名称,解决客户端与服务端命名不一致的问题。
using System.Runtime.Serialization;
[DataContract(Name = "OrderInfo", Namespace = "http://ipipp.com/contracts")]
public class Order
{
[DataMember(Name = "Id", Order = 1)]
public int OrderId { get; set; }
[DataMember(Name = "Buyer", Order = 2)]
public string CustomerName { get; set; }
// 没有 DataMember,不参与序列化
public string CacheKey { get; set; }
}
在服务契约层面,WCF默认就会采用DataContractSerializer,无需额外指定。但如果项目中混用了多种序列化需求,也可以在操作契约上通过ServiceContract和OperationContract的配合,或在绑定配置里显式设定。对于大多数内部系统,保持默认即可获得最佳兼容性与性能。
在服务端与客户端中控制序列化行为
DataContractSerializer提供了多个精细控制开关,例如通过DataMember的IsRequired和EmitDefaultValue来管理节点生成规则。当EmitDefaultValue设为false时,值为默认状态(如null或0)的成员将不出现在XML中,这能显著减少消息体积。在跨网络传输大量列表数据时,这一特性直接降低带宽消耗。
以下代码演示了如何抑制默认值输出,并要求某些字段必须存在。如果客户端发来的消息缺少Buyer节点,反序列化会抛出异常,从而提前拦截不合法请求。这种契约级别的约束比在业务代码里写判断更可靠,也更容易被框架优化。
[DataContract]
public class Product
{
[DataMember(IsRequired = true)]
public string Sku { get; set; }
[DataMember(EmitDefaultValue = false)]
public decimal? Discount { get; set; }
}
在客户端代理生成时,添加服务引用工具会读取服务元数据中的契约定义,自动生成对应的数据类。如果服务端调整了Name或Order,客户端重新生成即可同步,不需要手工修改XML映射。这也是DataContractSerializer相比手工处理XML文档的最大优势:契约即文档。
DataContractSerializer与XmlSerializer的对比及切换方式
尽管DataContractSerializer是默认选项,WCF仍允许在必要时切换到传统的XmlSerializer。后者对XML结构控制更细,支持属性(attribute)序列化、自定义节点顺序等老旧系统常需要的特性。但代价是必须暴露公共无参构造和公共属性,且无法利用契约的松散版本容错机制。
切换方式非常简单:在操作契约方法上添加[XmlSerializerFormat]特性即可。以下示例展示了同一服务中不同操作使用不同序列化器的写法。需要注意的是,一旦使用XmlSerializer,数据类就不需要DataContract标记,而是依靠XmlRoot、XmlElement等特性描述结构。
[ServiceContract]
public interface IReportService
{
[OperationContract]
[XmlSerializerFormat]
ReportData GetReportXml();
[OperationContract]
OrderInfo GetOrder();
}
从维护成本看,新项目应优先采用DataContractSerializer。它在版本演进时允许新增成员而不破坏旧客户端,且序列化速度通常快于XmlSerializer。只有在对接第三方严格规定XML Schema的场景下,才考虑切换。理解两者的适用边界,才能避免后期因格式不兼容导致的重构风险。
WCFDataContractSerializerXML序列化修改时间:2026-08-15 12:18:23