2010-07-28 12 views
23

Đôi khi tôi muốn mô phỏng dữ liệu được lưu trữ của các lớp mà không cần thiết lập một chuyến đi vòng đến cơ sở dữ liệu. Ví dụ, giả sử tôi có các lớp sau:Làm thế nào để tuần tự hóa/deserialize các lớp đơn giản thành XML và quay lại

public class ShoppingCart 
{ 
    public List<CartItem> Items {get; set;} 
    public int UserID { get; set; } 
} 

public class CartItem 
{ 
    public int SkuID { get; set; } 
    public int Quantity { get; set; } 
    public double ExtendedCost { get; set; } 
} 

Hãy nói rằng tôi xây dựng một đối tượng ShoppingCart trong bộ nhớ và muốn "cứu" nó như một tài liệu XML. Điều này có thể thông qua một số phương thức XDocument.CreateFromPOCO(shoppingCart) không? Còn theo một hướng khác: có cách tích hợp để tạo đối tượng ShoppingCart từ một tài liệu XML như new ShoppingCart(xDoc) không?

Trả lời

47

XmlSerializer là một cách để thực hiện. DataContractSerializer là loại khác. Ví dụ với XmlSerializer:

using System.Xml; 
using System.Xml.Serialization; 

//... 

ShoppingCart shoppingCart = FetchShoppingCartFromSomewhere(); 
var serializer = new XmlSerializer(shoppingCart.GetType()); 
using (var writer = XmlWriter.Create("shoppingcart.xml")) 
{ 
    serializer.Serialize(writer, shoppingCart); 
} 

và deserialize nó trở lại:

var serializer = new XmlSerializer(typeof(ShoppingCart)); 
using (var reader = XmlReader.Create("shoppingcart.xml")) 
{ 
    var shoppingCart = (ShoppingCart)serializer.Deserialize(reader); 
} 

Cũng cho đóng gói tốt hơn tôi sẽ khuyên bạn sử dụng thuộc tính thay vì các lĩnh vực trong lớp CartItem của bạn.

+0

Cảm ơn đề xuất. Tôi đã có ý định sử dụng các thuộc tính thay vì các trường. Đã sửa. –

+0

Tôi mất một thời gian để thử nghiệm điều này, nhưng nó hoạt động hoàn hảo. Cảm ơn! –

+3

Tôi ước tôi có thể cung cấp cho bạn một ý kiến ​​cho mỗi lần tôi đã điều hướng đến câu trả lời này trong vài tuần qua. Nó giữ trả cổ tức! –

2

Bạn có thể tuần tự hóa/deserialize bằng số hoặc DataContractSerializer.

Chú thích các lớp học của bạn với các thuộc tính DataContractDataMember và viết thứ gì đó tương tự như thế này để tuần tự hóa thành xml thành tệp.

ShoppingCart cart = ... 
using(FileStream writer = new FileStream(fileName, FileMode.Create)) 
{ 
    DataContractSerializer ser = new DataContractSerializer(typeof(ShoppingCart)); 
    ser.WriteObject(writer, cart); 
} 
+0

Điều gì sẽ xảy ra nếu ngoại lệ bị ném trong quá trình tuần tự hóa? –

+1

@Darin: Bạn thường gặp phải điều này khi bắt đầu sử dụng DataContractSerializer. Nhưng nó thường nhổ xuống thuộc tính chú thích của các lớp của bạn. XmlSerializer dễ sử dụng hơn vì nó chiếm hầu như bất cứ thứ gì bạn ném vào nó, nhưng DataContractSerializer nhanh hơn, nhưng đòi hỏi nhiều công việc hơn để làm cho nó hoạt động. –

+0

@Mikael, tôi nghĩ rằng bạn đã không nhận được quan điểm của tôi. Điều tôi muốn nói là nếu một ngoại lệ bị ném, bạn sẽ bị rò rỉ một tập tin rất tệ vì nó sẽ khóa tập tin và không quá trình nào khác có thể làm bất cứ điều gì với nó cho đến khi bạn giết ứng dụng. –

0

Chỉ cần đánh dấu những gì bạn muốn serialize với [XmlElement (tên)] (hoặc XmlAttribute, XmlRoot, vv) và sau đó sử dụng XmlSerializer. Nếu bạn cần định dạng tùy chỉnh, hãy triển khai IXmlSerializable.

+2

Tại sao không cung cấp mẫu mã giống như các câu trả lời khác trên chuỗi? – Konstantin

7

Được thực hiện tốt. Đây là ví dụ để tuần tự hóa POCO đơn giản thành chuỗi.

private string poco2Xml(object obj) 
    { 
     XmlSerializer serializer = new XmlSerializer(obj.GetType()); 
     StringBuilder result = new StringBuilder(); 
     using (var writer = XmlWriter.Create(result)) 
     { 
      serializer.Serialize(writer, obj); 
     } 
     return result.ToString(); 
    }