2009-08-18 3 views
28

XmlSerializer.DeserializeXDocument으로 전달하고 싶습니다. XmlReader 또는 TextReader 일 수는 Stream입니다.XDocument를 XmlSerializer.Deserialize의 원본으로 사용 하시겠습니까?

실제로 XDocumentMemoryStream과 같은 중간 저장소에 덤프하지 않고 위의 중 하나를 생성 할 수 있습니까?

XDocument과 함께 작동하는 XmlReader의 구현입니다. 나는 하나를 찾을 수 없습니다.

+0

내가 이것에 대한 해결책을 찾기 위해 기대했다 또한 http://stackoverflow.com/q/7901558/11912 –

답변

43

XDocument.CreateReader()을 사용하면 XDocument의 내용을 읽는 XmlReader을 만들 수 있습니다.

마찬가지로 다음과 같이 작동합니다.

XmlSerializer serializer = new XmlSerializer(typeof(MyObject)); 
XmlReader reader = xmlDocumentToDeserialize.CreateReader(); 

는 다음 호출해야합니다 :

XmlReader GetReader(XDocument doc) 
{ 
    return doc.Root.CreateReader(); 
} 
0

그냥 내가 XmlReader를 만든 후, 즉 것을 추가해야한다고 생각

reader.MoveToContent(); 

때문에 다른 독자하지 않습니다 "포인트"에 첫 번째 노드는 빈 리더의 출현을 초래합니다! 그런 다음 Deserialize를 안전하게 호출 할 수 있습니다.

MyObject myObject = (MyObject)serializer.Deserialize(reader); 
9

다음은 XDocument와 개체를 직렬화 및 비 직렬화하는 유틸리티입니다. 여기

XDocument doc = SerializationUtil.Serialize(foo); 
Foo foo = SerializationUtil.Deserialize<Foo>(doc); 

클래스입니다 :

public static class SerializationUtil 
{ 
    public static T Deserialize<T>(XDocument doc) 
    { 
     XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 

     using (var reader = doc.Root.CreateReader()) 
     { 
      return (T)xmlSerializer.Deserialize(reader); 
     } 
    } 

    public static XDocument Serialize<T>(T value) 
    { 
     XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 

     XDocument doc = new XDocument(); 
     using (var writer = doc.CreateWriter()) 
     { 
      xmlSerializer.Serialize(writer, value); 
     } 

     return doc; 
    } 
} 
3

지금까지 내가 쉽게 이동하지 않고 XDocument와 함께 사용할 수있는 XmlReader의 구현이 존재하지 않는 볼 수있다 (스티브 구이 디의 대답 부록)

을 예를 들어 System.Xml.XmlNodeReader이 지원하는 모든 유형의을 지원하는 등 XML의 문자열 표현과 같은 중간 저장소를 통한 XML 콘텐츠

(A System.Xml.Linq.XNodeReader, 내부 클래스 인) XDocument.CreateReader에 의해 반환되는 독자는 XmlReader이며 대부분의 XML 문서에 대한 아니라 이진 데이터 요소가 문서와 함께 작동하기 때문에 구현 does not support Base64 or BinHex data :

Base64로 및 BinHex 데이터는 지원되지 않습니다. 이러한 유형의 데이터를 (예 : ReadElementContentAsBase64를 호출하여) 검색하려고하면 리더는 NotSupportedException을 throw합니다. 이 리더 XDocument.CreateReader().CanReadBinaryContent 들어

System.Xml.XmlNodeReader 달리 false이다.이 프로그램은 예외가 발생합니다 예를 들어

: string로 XML을 추출하여 시리얼로 TextReader로 전달 그러나

public class SomeTest 
{ 
    public byte[] BinaryTest { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     XDocument document = new XDocument(
      new XElement("SomeTest", 
       new XElement("BinaryTest", "VGVzdA=="))); 

     using (var reader = document.CreateReader()) 
     { 
      var serializer = new XmlSerializer(typeof(SomeTest)); 
      var someTest = serializer.Deserialize(reader) as SomeTest; 
      // NotSupportedException here (as inner exception) 
     } 
    } 
} 

작동 :

 using (var reader = new StringReader(document.ToString())) 

은 나뿐만 아니라 경우에 관심이있을 것 이진 데이터를 문자열로 변환하지 않고 포함하는 XDocument을 비 직렬화하는 다른 방법이 있습니다.

+0

참조하십시오. 바이너리 데이터로 일부 XML 컨텐트를 가지므로 모든 것을 훨씬 느리게 만듭니다. 문자열로의 라운드 트립은 정신 나간 것 같습니다. 나는 성능에 치중하기보다는 바이트 [] 내용을 모두 삭제하려고 협상 할 것이라고 생각한다. – Jim

0

@Simon_Weaver의 답변이 가장 좋습니다. 이 내 요약 한 것을 기반으로 :

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

namespace XDocSerialization 
{ 
    [TestClass] 
    public class Tests 
    { 
     [TestMethod] 
     public void Tests_SerializeToXDoc() 
     { 
      var sheep = new Animal 
      { 
       Name = "Sheep", Legs = 4, Nutrition = Nutrition.Herbivore 
      }; 
      var xdoc = sheep.SerializeToXDoc(); 
      var ser = "<Animal " + 
         "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + 
         "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n " + 
         "<Name>Sheep</Name>\r\n <Legs>4</Legs>\r\n " + 
         "<Nutrition>Herbivore</Nutrition>\r\n</Animal>"; 

      Assert.AreEqual(xdoc.ToString(), ser); 
      Assert.IsInstanceOfType(xdoc, typeof(XDocument)); 
     } 

     [TestMethod] 
     public void Tests_DeserializeFromXDoc() 
     { 
      var Sheep = new Animal 
      { 
       Name = "Sheep", Legs = 4, Nutrition = Nutrition.Herbivore 
      }; 
      var des = Sheep.SerializeToXDoc().DeserializeFromXDoc<Animal>(); 

      Assert.AreEqual(des.Name, Sheep.Name); 
      Assert.AreEqual(des.Nutrition, Sheep.Nutrition); 
      Assert.AreEqual(des.Legs, Sheep.Legs); 
      Assert.AreNotSame(des, Sheep); 
     } 
    } 

    public static class ExtensionMethods 
    { 
     public static T DeserializeFromXDoc<T>(this XDocument source) 
     { 
      if (source == null || source.Root == null) 
       return default(T); 

      using (var reader = source.Root.CreateReader()) 
       return (T)new XmlSerializer(typeof(T)).Deserialize(reader); 
     } 

     public static XDocument SerializeToXDoc<T>(this T source) 
     { 
      if (source == null) 
       return null; 

      var doc = new XDocument(); 
      using (var writer = doc.CreateWriter()) 
       new XmlSerializer(typeof(T)).Serialize(writer, source); 

      return doc; 
     } 
    } 

    [Serializable] 
    public class Animal 
    { 
     public string Name { get; set; } 
     public int Legs { get; set; } 
     public Nutrition Nutrition { get; set; } 
    } 

    public enum Nutrition 
    { 
     Herbivore, 
     Carnivore, 
     Omnivore 
    } 
} 
관련 문제