2010-07-28 2 views
23

간혹 데이터베이스에 대한 왕복을 설정하지 않고 클래스의 저장된 데이터를 에뮬레이트하려고합니다. 예를 들어, 나는 다음과 같은 클래스가 있다고 가정 해 봅시다 : 간단한 클래스를 XML로 직렬화/역 직렬화하는 방법

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

이의 내가 메모리에 ShoppingCart 객체를 구축하고 XML 문서로 "저장"하기를 원하는 경우를 생각 해보자. 가능한 일종의 XDocument.CreateFromPOCO(shoppingCart) 방법을 통해 가능합니까? 다른 방향은 어떨까요 : new ShoppingCart(xDoc)과 같은 XML 문서에서 ShoppingCart 개체를 만드는 기본 제공 방법이 있습니까?

답변

47

XmlSerializer은이를 수행하는 한 가지 방법입니다. DataContractSerializer은 다른 것입니다. 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); 
} 

하고 다시 역 직렬화하기 :

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

은 또한 더 나은 캡슐화 나는 당신의 CartItem 클래스의 필드 대신 속성을 사용하여 당신을 추천 할 것입니다.

+0

제안 해 주셔서 감사합니다. 필드 대신 속성을 사용하려고했습니다. 결정된. –

+0

테스트하는 데 시간이 좀 걸렸지 만 완벽하게 작동했습니다. 감사! –

+3

지난 몇 주 동안이 답변을 탐색 할 때마다 upvote를 줄 수 있기를 바랍니다. 그것은 배당금을 지불하고 있습니다! –

2

또는 DataContractSerializer을 사용하여 직렬화/역 직렬화 할 수 있습니다.

클래스에 DataContractDataMember 속성을 주석으로 추가하고 이와 같이 작성하여 xml을 파일로 serialize하십시오.

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

직렬화 중에 예외가 throw되면 어떻게됩니까? –

+1

@Darin : DataContractSerializer를 사용하기 시작할 때 자주 접하게 될 것입니다. 그러나 일반적으로 클래스의 주석을 특성화하기 위해 종결됩니다. XmlSerializer는 사용자가 던지는 것이 무엇이든간에 거의 사용하기 때문에 사용하기 쉽지만 DataContractSerializer는 빠르지 만 작동 시키려면 더 많은 "작업"이 필요합니다. –

+0

@Mikael, 내 생각을 못 알아 냈어. 내가 의미했던 것은 예외가 발생하면 파일을 잠글 것이고 다른 프로세스가 응용 프로그램을 죽일 때까지 아무 것도 할 수 없으므로 파일 핸들이 누출 될 것입니다. –

0

는 그냥 [XMLELEMENT (이름)] (또는있는 XmlAttribute, XmlRoot 등)로 직렬화하고 XmlSerializer를 사용하려는 무슨 표시합니다. 정말로 사용자 정의 포매팅이 필요하면 IXmlSerializable을 구현하십시오.

+2

스레드의 다른 답변과 같은 코드 샘플을 제공하지 않는 이유는 무엇입니까? – Konstantin

7

멋지게 완료되었습니다. 다음은 문자열에 일반 POCO를 직렬화하는 예입니다.

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(); 
    } 
관련 문제