2017-07-27 25 views
4

我很困惑XmlSerializer如何在幕後工作。我有一個類將XML反序列化爲一個對象。我所看到的是以下兩個不是被反序列化的Xml組成部分的元素。C#Xml串行器將列表反序列化爲0而不是null

[XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)] 
public class MyClass 
{ 
    private string comments; 
    public string Comments 
    { 
     set { comments = value; } 
     get { return comments; } 
    } 

    private System.Collections.Generic.List<string> tests = null; 
    public System.Collections.Generic.List<string> Tests 
    { 
     get { return tests; } 
     set { tests = value; } 
    } 
} 

讓我們以下面的XML作爲例子:

<MyClass> 
    <SomeNode>value</SomeNode> 
</MyClass> 

你注意到測試和評論不屬於XML的一部分。

當這個XML被反序列註釋爲空(預期)和測試是一個空列表與0

計數如果有人可以解釋這對我來說將是非常讚賞。我更喜歡的是,如果<Tests>從XML中丟失,那麼列表應該保持爲空,但是如果存在(可能爲空)節點<Tests />,那麼該列表應該被分配。

+0

@gdir你是說當你序列化這個你得到一個空值列表而不是空列表? – Maxqueue

+0

沒有我問的是,因爲測試不是XML的一部分,當序列化它應該爲空而不是空列表。那有意義嗎? – Maxqueue

+2

OP的問題是關於反序列化而不是序列化。當上面的XML被反序列化時,即使'XML'中沒有出現'',也會分配'tests'集合。 (順便說一句,我可以重現它。) – dbc

回答

2

您正在觀察的是,引用可修改集合的成員(如List<T>)會在反序列化開始時自動預分配XmlSerializer。我不知道這個行爲有記錄的地方。 ,這可能與在this answerXML Deserialization of collection property with code defaults描述的行爲,這也說明,由於XmlSerializersupports adding to get-only and pre-allocated collections如果預先分配的集合包含然後反序列化的項目將被追加到默認項 - 可能是重複的內容。微軟可能簡單地選擇在反序列化開始時預先分配全部可修改集合作爲實現這一點的最簡單方法。

該答案的解決方法即使用代理數組屬性也適用於此。由於無法附加數組,因此XmlSerializer必須累積所有值並在反序列化完成時將其設置回去。但是如果從未遇到相關標記,XmlSerializer顯然不會開始累加值,因此不會調用數組setter。這似乎是防止藏品的默認預分配,你不想要的:

[XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)] 
public class MyClass 
{ 
    private string comments; 
    public string Comments 
    { 
     set { comments = value; } 
     get { return comments; } 
    } 

    private System.Collections.Generic.List<string> tests = null; 

    [XmlIgnore] 
    public System.Collections.Generic.List<string> Tests 
    { 
     get { return tests; } 
     set { tests = value; } 
    } 

    [XmlArray("Tests")] 
    public string[] TestsArray 
    { 
     get 
     { 
      return (Tests == null ? null : Tests.ToArray()); 
     } 
     set 
     { 
      if (value == null) 
       return; 
      (Tests = Tests ?? new List<string>(value.Length)).AddRange(value); 
     } 
    } 
} 

樣品.Net fiddle只顯示在適當的時候是Tests分配。

+0

非常翔實的謝謝。 – Maxqueue