2012-03-06 23 views
10

我注意到XmlSerializer和通用列表(特別是List<int>)奇怪的行爲。我想知道是否有人曾經見過或知道發生了什麼。它看起來好像序列化工作正常,但反序列化想要添加額外的項目到列表中。下面的代碼演示了這個問題。反序列化列表<int>與XmlSerializer導致額外項目

Serializable類:

public class ListTest 
{ 
    public int[] Array { get; set; } 
    public List<int> List { get; set; } 

    public ListTest() 
    { 
     Array = new[] {1, 2, 3, 4}; 
     List = new List<int>(Array); 
    } 
} 

測試代碼:

ListTest listTest = new ListTest(); 
Debug.WriteLine("Initial Array: {0}", (object)String.Join(", ", listTest.Array)); 
Debug.WriteLine("Initial List: {0}", (object)String.Join(", ", listTest.List)); 

XmlSerializer serializer = new XmlSerializer(typeof(ListTest)); 
StringBuilder xml = new StringBuilder(); 
using(TextWriter writer = new StringWriter(xml)) 
{ 
    serializer.Serialize(writer, listTest); 
} 

Debug.WriteLine("XML: {0}", (object)xml.ToString()); 

using(TextReader reader = new StringReader(xml.ToString())) 
{ 
    listTest = (ListTest) serializer.Deserialize(reader); 
} 

Debug.WriteLine("Deserialized Array: {0}", (object)String.Join(", ", listTest.Array)); 
Debug.WriteLine("Deserialized List: {0}", (object)String.Join(", ", listTest.List)); 

調試輸出:

Initial Array: 1, 2, 3, 4 
Initial List: 1, 2, 3, 4 

XML:

<?xml version="1.0" encoding="utf-16"?> 
<ListTest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Array> 
    <int>1</int> 
    <int>2</int> 
    <int>3</int> 
    <int>4</int> 
    </Array> 
    <List> 
    <int>1</int> 
    <int>2</int> 
    <int>3</int> 
    <int>4</int> 
    </List> 
</ListTest> 
Deserialized Array: 1, 2, 3, 4 
Deserialized List: 1, 2, 3, 4, 1, 2, 3, 4 

請注意,數組和列表似乎都已正確地序列化爲XML,但是在反序列化中,數組出現正確,但列表中出現了一組重複的項目。有任何想法嗎?

+1

謝謝你的答案 - 正如我在下面的評論中提到的,我不知道解串器能夠反序列化過程變異成員的狀態(在大多數情況下,我認爲它只是設置新的價值觀,對不對? )。是列表它可以做到這一點的唯一類?是否有一些引用指出解串器可以改變哪些類? – daveaglick 2012-03-06 18:33:42

回答

7

這是因爲您正在構造函數中初始化列表。當你去反序列化時,一個新的ListTest被創建,然後它從狀態填充對象。

這樣想

  1. 工作流程的創建一個新的ListTest
  2. 執行構造函數(加1,2,3,4)
  3. 反序列化XML狀態,並添加1,2, 3,4到列表

一個簡單的解決方案將是初始化的構造的範圍之外的對象。

public class ListTest 
{ 
    public int[] Array { get; set; } 
    public List<int> List { get; set; } 

    public ListTest() 
    { 

    } 

    public void Init() 
    { 
     Array = new[] { 1, 2, 3, 4 }; 
     List = new List<int>(Array); 
    } 
} 

ListTest listTest = new ListTest(); 
listTest.Init(); //manually call this to do the initial seed 
3

問題是,您在默認構造函數的List中定義了原始的1,2,3,4。您的反序列化程序正在添加到列表中,而不是定義它。

+3

謝謝,移動構造函數的初始化確實解決了這個問題。我誤解了解串器的工作原理。我沒有意識到它改變了現有的對象,我認爲它總是使用set訪問器爲全新構造的對象寫入全新的子對象實例(在這種情況下,構造函數中創建的列表將會被忘記)。你每天都會學到東西。 – daveaglick 2012-03-06 18:31:01

相關問題