2013-08-27 69 views
2

我有以下數據契約:爲什麼需要DataContractSerializer按字母順序排序XML?

namespace Wcf.Contracts.Data 
{ 
    [DataContract] 
    public class Presence 
    { 
    [DataMember] 
    public int Id { get; set; } 

    [DataMember] 
    public DateTime? From { get; set; } 

    [DataMember] 
    public DateTime? To { get; set; } 

    [DataMember] 
    public TimeSpan? BreakPeriod { get; set; } 
    } 
} 

序列化的Presence一個實例XML和反序列化相同的XML回Presence作品的實例很好。但是反序列化一個代表序列化對象的字符串變量給了我奇怪的行爲。一些屬性獲得了默認值,而不是來自XML的指定值。我發現代表Presence屬性的XML中的元素必須按字母順序排列。

例如,在此代碼段的代碼

var dcs = new System.Runtime.Serialization.DataContractSerializer(typeof(Wcf.Contracts.Data.Presence)); 

var xml1 = @"<?xml version=""1.0"" encoding=""utf-16""?> 
<Presence xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.datacontract.org/2004/07/Wcf.Contracts.Data""> 
    <BreakPeriod>PT30M</BreakPeriod> 
    <From>2013-08-21T10:00:00Z</From> 
    <To>2013-08-21T15:00:00Z</To> 
    <Id>85</Id> 
</Presence>"; 
var xr1 = System.Xml.XmlReader.Create(new System.IO.StringReader(xml1)); 
var p1 = dcs.ReadObject(xr1) as Wcf.Contracts.Data.Presence; 

var xml2 = @"<?xml version=""1.0"" encoding=""utf-16""?> 
<Presence xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.datacontract.org/2004/07/Wcf.Contracts.Data""> 
    <Id>85</Id> 
    <From>2013-08-21T10:00:00Z</From> 
    <To>2013-08-21T15:00:00Z</To> 
    <BreakPeriod>PT30M</BreakPeriod> 
</Presence>"; 
var xr2 = System.Xml.XmlReader.Create(new System.IO.StringReader(xml2)); 
var p2 = dcs.ReadObject(xr2) as Wcf.Contracts.Data.Presence; 

var xml3 = @"<?xml version=""1.0"" encoding=""utf-16""?> 
<Presence xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.datacontract.org/2004/07/Wcf.Contracts.Data""> 
    <BreakPeriod>PT30M</BreakPeriod> 
    <From>2013-08-21T10:00:00Z</From> 
    <Id>85</Id> 
    <To>2013-08-21T15:00:00Z</To> 
</Presence>"; 

var xr3 = System.Xml.XmlReader.Create(new System.IO.StringReader(xml3)); 
var p3 = dcs.ReadObject(xr3) as Wcf.Contracts.Data.Presence; 

三個實例都不同。

  | p1     | p2       | p3 
Id   | default(int) (=0)  | 85       | 85 
From  | 8/21/2013 10:00:00 AM | default(DateTime?) (=null) | 8/21/2013 10:00:00 AM 
To   | 8/21/2013 3:00:00 PM | 8/21/2013 3:00:00 PM  | 8/21/2013 3:00:00 PM 
BreakPeriod | 00:30:00    | default(TimeSpan?) (=null) | 00:30:00 

爲什麼要對XML中的元素進行排序?有誰知道爲什麼DataContractSerializer否則不正確反序列化?

+0

+1發佈工作示例。 – Sphinxxx

+1

[使用DataContractSerializer反序列化XML]可能的重複(http://stackoverflow.com/questions/15413468/deserializing-xml-with-datacontractserializer) – chwarr

回答

2

這很正常。 datacontract將描述soap消息的xml模式。 DataContractSerializer使用任意字母順序。您可以通過指定更改訂單:

[DataMember(Order = 1)] 
    public int MyProperty { get; set; } 

爲什麼需要指定訂單?我沒有時間閱讀SOAP RFC,但我認爲它是正常化的。

如果我們考慮一下,這是速度和尺寸優化的邏輯。 DataContract通過不爲null屬性值寫入任何xml來指定null。想象一下,如果你有一個具有200個屬性的對象,你必須讀取所有的xml以確定屬性是否爲null。如果你有一個訂購元素的xml模式,它會更快。

我希望我不得不說的是促成了一個更好的理解。