WCF禁用反序列化顺序灵敏度

30 .net wcf serialization

在非.NET客户端和.NET WCF服务之间传递序列化对象时,我遇到了一个反复出现的问题.

当WCF反序列化对象时,它严格依赖于属性的顺序.

也就是说,如果我将我的类定义为:

public class Foo 
{ 
  public int ID { get; set; } 
  public int Bar { get; set; } 
} 
Run Code Online (Sandbox Code Playgroud)

然后WCF将序列化对象,如下所示:

<Foo>
  <Bar>123</Bar>
  <ID>456</ID>
</Foo>
Run Code Online (Sandbox Code Playgroud)

注意:属性按字母顺序序列化.

如果您尝试反序列化具有BarID交换位置的对象,WCF会将错误定位的元素视为null.

虽然我知道我可以使用该DataMember属性,并强制执行特定的排序,但我希望减少调试字段"神秘"为空的问题的次数.

所以,我的问题是:在反序列化对象时,是否可以告诉WCF反序列化器忽略字段的顺序.

mar*_*c_s 12

您可以通过修改数据协定中的元素来指定序列化顺序:

[DataContract]
public class Foo 
{ 
  [DataMember(Order=1)]
  public int ID { get; set; } 

  [DataMember(Order=2)]
  public int Bar { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以确保序列化顺序始终相同.但是没有办法告诉解串器"忘记"顺序 - 重点是:这是通过XML模式处理的,并且使用<xs:sequence>元素完成- 这确实意味着需要顺序.我担心,你不能把它关掉.

基于该XML模式,您的非.NET客户端应该能够验证他们将要发送的XML是否符合该模式 - 如果不是因为Bar和ID元素已被交换,他们不应该发送无效的XML.


Joe*_*Joe 10

您可以使用DataMember属性的IsRequired属性指定元素是必需的.这样,您将获得更明确的错误消息,表明缺少必需的元素,而不是获得"神秘"的空值.

[DataContract]
public class Foo 
{ 
  [DataMember(IsRequired=true, Order=1)]
  public int ID { get; set; } 

  [DataMember(IsRequired=true, Order=2)]
  public int Bar { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

您的案例中发生的事情是:

  • DataContract按此顺序需要Bar和ID元素(字母表,因为您没有指定显式顺序).

  • 它遇到没有前面的Bar元素的ID元素.由于Bar不是必需的,它只是忽略它.

  • Bar后面的ID元素被忽略,因为它位于错误的位置.

话虽如此,将IsRequired设置为true只会对合同的第1版有所帮助.后续版本中添加的元素通常将IsRequired设置为false.MSDN有一篇关于数据合同版本控制的文章.


Pau*_*ell 7

这里有一个旧线程:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/a891928b-d27a-4ef2-83b3-ee407c6b9187

看起来唯一的选择是交换串行器,但随后它变得选择,这更令人讨厌.

编辑:您可以编写自己的序列化程序来重新排序元素,然后将其传递给DataContractSerializer.

  • 有趣.现在只是编写一个抓取消息的拦截器,询问WCF mehtod以找出预期的类型,使用XmlSerializer进行反序列化(根据线程确实有效),并使用DataContractSerializer重新序列化.多么简单;)仍然......可能是实际按预期工作的唯一解决方案.谢谢 :) (3认同)