2009-08-18 70 views
28

我想請XmlSerializer.Deserialize通過它XDocument。它可以採取Stream,XmlReaderTextReader使用XDocument作爲XmlSerializer.Deserialize的源代碼?

我可以在沒有將XDocument實際轉儲到某個中間商店(如MemoryStream)的情況下生成XDocument中的上述一個嗎?

看來,我所追求的是XmlReader的實施,它與XDocument一起使用。我找不到一個。

+0

也http://stackoverflow.com/q/7901558/11912 – 2013-01-05 15:00:50

回答

43

您可以使用XDocument.CreateReader()創建一個讀取XDocument的內容的XmlReader

等效地,下面也會起作用。

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

只是想我要補充一點,在創建的XmlReader後,即:

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

那麼你應該叫:

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

(附錄史蒂夫·圭迪的答案)

至於我可以看到有沒有XmlReader實現,你可以輕鬆地與XDocument使用,而無需移動通過中間商店的XML內容,如XML和的字符串表示,支持所有類型,例如System.Xml.XmlNodeReader支持的所有類型。

XDocument.CreateReader返回(這是一個System.Xml.Linq.XNodeReader,一個內部類)的讀者是一個XmlReader並適用於大多數的XML文檔,但不能與具有二進制數據元素的文檔,因爲它的實現does not support Base64 or BinHex data

Base64和BinHex數據不受支持。如果您嘗試檢索 這些類型的數據(例如,通過調用 ReadElementContentAsBase64),讀者將拋出 NotSupportedException。

對於此讀者XDocument.CreateReader().CanReadBinaryContentfalseSystem.Xml.XmlNodeReader相反。

例如該程序會拋出異常:

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

然而,提取XML作爲string,並把它當作TextReader串行化器的工作原理:

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

我會感興趣,以及如果還有另一種方法來反序列化包含二進制數據的XDocument,而不先將其轉換爲字符串。

+0

看,我希望能找到這個決議。我有一些xml內容與二進制數據,這將使一切慢得多。一輪跳到一個字符串似乎瘋了。我想我可能會嘗試和談判放棄字節[]內容,而不是採取性能命中。 – Jim 2016-03-03 12:31:30

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 
    } 
} 
相關問題