为什么WCF DataContract不按字母顺序序列化成员
本文关键字:顺序 序列化 成员 WCF DataContract 为什么 | 更新日期: 2023-09-27 18:22:36
我有几个DataContract
看起来与此类似(为简洁起见,缩写为)
[DataContract(Name = "ItemDTO", Namespace = "http://foo.com/")]
public class ItemDTO : IExtensibleDataObject
{
[DataMember(IsRequired = true)]
public string Name { get; set; }
[DataMember]
public string Value { get; set; }
[DataMember(IsRequired = true)]
public int Id { get; set; }
public ExtensionDataObject ExtensionData { get; set; }
}
我以前没有注意到序列化的消息,但在最近的一次更改之后,我做了两件事:我添加了一个名为ReturnCode
的新属性,并运行CodeMaid的"Reorganize",该属性按字母顺序排列。
现在看起来是这样的:
[DataContract(Name = "ItemDTO", Namespace = "http://foo.com/")]
public class ItemDTO : IExtensibleDataObject
{
public ExtensionDataObject ExtensionData { get; set; }
[DataMember(IsRequired = true)]
public int Id { get; set; }
[DataMember(IsRequired = true)]
public string Name { get; set; }
[DataMember]
public int ReturnCode { get; set; }
[DataMember]
public string Value { get; set; }
}
根据微软关于数据合同成员订单的页面,我意识到ReturnCode
会破坏合同,因为序列化程序会将其插入Value
之前,所以我添加了一个Order
属性值,假设原始订单是字母顺序,得到:
[DataContract(Name = "ItemDTO", Namespace = "http://foo.com/")]
public class ItemDTO : IExtensibleDataObject
{
public ExtensionDataObject ExtensionData { get; set; }
[DataMember(IsRequired = true, Order = 0)]
public int Id { get; set; }
[DataMember(IsRequired = true, Order = 1)]
public string Name { get; set; }
[DataMember(Order = 3)]
public int ReturnCode { get; set; }
[DataMember(Order = 2)]
public string Value { get; set; }
}
然而,这引发了一个异常,即反序列化的成员出现故障。在所有更改之前,我回滚到以前的变更集,确信成员的原始顺序在SOAP请求中不是字母顺序(通过Fiddler查看),而是遵循代码中表达的原始顺序,即:Name
、Value
、Id
。
我目前正在将Order
值添加到我所有的旧DTO类型中,以根据它们之前的属性、排列的字母顺序对它们进行排序。我想知道的是为什么序列化程序使用编码顺序而不是字母顺序?微软的规则说:
接下来是当前类型的数据成员,它们没有中的DataMemberAttribute属性集的Order属性按字母顺序。
更新:
在我添加了Order
值以按其原始顺序对属性进行排序后,我再次运行Fiddler,它仍然使用项目的实际编码顺序。换句话说,出于某种原因,我的WCF服务完全忽略了任何序列化排序逻辑,只按属性在.cs文件中的显示顺序对其进行排序。事实上,我能够使它正确序列化的唯一方法是将每个类型中的属性物理地重新排列到它们的原始顺序。这是有效的,但不是首选。
更新2-解决方案:
根据Dracor的建议,我在DTO中添加了[XmlElement(Order = 1)]
属性和一个XmlRootAttribute
。SOAP序列化DID最终遵循这些属性分配的顺序。我没有考虑过,但我的服务确实使用了Castle DynamicProxy,所以我猜它正在将序列化程序从DataContractSerializer
更改为XmlSerializer
。
为什么不简单地使用XmlSerializer来序列化/反序列化XML?它比DataContractSerializer宽容得多,并且在大多数情况下都有效。