2012-03-06 10 views
10

Tôi nhận thấy một hành vi kỳ lạ với XmlSerializer và danh sách chung (cụ thể là List<int>). Tôi đã tự hỏi nếu có ai đã nhìn thấy điều này trước hoặc biết những gì đang xảy ra. Nó xuất hiện như thể serialization hoạt động tốt nhưng deserialization muốn thêm các mục bổ sung vào danh sách. Mã bên dưới minh họa sự cố.Deserializing List <int> với XmlSerializer Gây thêm các mục

lớp Serializable: Mã

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); 
    } 
} 

Test:

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)); 

gỡ lỗi đầu ra:

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 

Lưu ý rằng cả mảng và danh sách dường như đã được tuần tự hóa thành XML một cách chính xác nhưng trên deserialization mảng xuất hiện chính xác nhưng danh sách trở lại với một tập hợp các mục trùng lặp. Bất kỳ ý tưởng?

+1

Cảm ơn câu trả lời - như tôi đã đề cập trong một chú thích dưới đây, tôi đã không nhận ra deserializer đã có thể đột biến tình trạng của các thành viên trong deserialization (trong hầu hết trường hợp tôi nghĩ rằng nó chỉ đặt những giá trị mới, phải không?). Danh sách là lớp duy nhất nó có thể làm điều này với? Có một số tham chiếu cho biết các lớp deserializer có thể đột biến không? – daveaglick

Trả lời

7

Điều này xảy ra vì bạn đang khởi tạo Danh sách trong hàm tạo. Khi bạn đi đến deserialize, một ListTest mới được tạo ra và sau đó nó cư trú đối tượng từ nhà nước.

Hãy suy nghĩ về những công việc như thế này

  1. Tạo một ListTest mới
  2. Thực hiện các Constructor (thêm 1,2,3,4)
  3. Deserialize tình trạng xml, và thêm 1,2, 3,4 vào Danh sách

Một giải pháp đơn giản là bắt đầu đối tượng nằm ngoài phạm vi của hàm tạo.

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

Vấn đề là bạn đang xác định 1,2,3,4 ban đầu trong Danh sách trong hàm dựng mặc định. Trình giải mã của bạn đang thêm vào danh sách, không xác định nó.

+3

Cảm ơn, di chuyển khởi tạo ra khỏi các nhà xây dựng đã thực sự giải quyết vấn đề. Tôi hiểu lầm cách deserializer hoạt động. Tôi đã không nhận ra nó làm biến đổi các đối tượng hiện có, tôi nghĩ nó luôn sử dụng bộ accessor để viết các thể hiện hoàn toàn mới cho các đối tượng mới được xây dựng (trong trường hợp danh sách được tạo trong constructor sẽ bị quên). Bạn học được điều gì đó mỗi ngày. – daveaglick