.net 使用 XDocument 作为 XmlSerializer.Deserialize 的源?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1295046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use XDocument as the source for XmlSerializer.Deserialize?
提问by Roman Starkov
I would like to invoke XmlSerializer.Deserializepassing it an XDocument. It can take a Stream, an XmlReaderor a TextReader.
我想调用XmlSerializer.Deserialize将它传递给XDocument. 它可以采用 a Stream、 anXmlReader或 a TextReader。
Can I generate one of the above from XDocumentwithout actually dumping the XDocumentinto some intermediate store, such as a MemoryStream?
我可以在XDocument不实际将其转储XDocument到某些中间存储中的情况下生成上述之一MemoryStream吗?
It seems that what I'm after is an implementation of XmlReaderthat works with an XDocument. I can't find one though.
似乎我所追求的是一个XmlReader与XDocument. 虽然我找不到。
回答by Steve Guidi
You can use XDocument.CreateReader()to create an XmlReaderthat reads the contents of the XDocument.
您可以使用XDocument.CreateReader()创建一个XmlReader读取XDocument.
Equivalently, the following will work too.
同样,以下也将起作用。
XmlReader GetReader(XDocument doc)
{
return doc.Root.CreateReader();
}
回答by Simon_Weaver
Here's a utility to serialize and deserialize objects to/from XDocument.
这是一个用于将对象序列化和反序列化到/从 XDocument 的实用程序。
XDocument doc = SerializationUtil.Serialize(foo);
Foo foo = SerializationUtil.Deserialize<Foo>(doc);
Here's the class:
这是课程:
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;
}
}
回答by Slauma
(Appendix to Steve Guidi's answer)
(Steve Guidi 回答的附录)
As far as I can see there is no implementation of XmlReaderyou can easily use with XDocumentwithout moving the XML content through an intermediate store like a string representation of the XML and that supports all typesthat for example the System.Xml.XmlNodeReadersupports.
据我所知,没有任何实现XmlReader可以轻松使用,XDocument而无需通过中间存储移动 XML 内容,例如XML 的字符串表示形式,并且支持所有类型,例如System.Xml.XmlNodeReader支持的类型。
The reader returned by XDocument.CreateReader(which is a System.Xml.Linq.XNodeReader, an internal class) is a XmlReaderand works for most Xml document but not with documents that have binary data elements because its implementation does not support Base64 or BinHex data:
由XDocument.CreateReader(它是一个System.Xml.Linq.XNodeReader内部类)返回的读取器是 aXmlReader并且适用于大多数 Xml 文档,但不适用于具有二进制数据元素的文档,因为它的实现不支持 Base64 或 BinHex 数据:
Base64 and BinHex data are not supported. If you attempt to retrieve these types of data (for example, by calling ReadElementContentAsBase64), the reader will throw NotSupportedException.
不支持 Base64 和 BinHex 数据。如果您尝试检索这些类型的数据(例如,通过调用 ReadElementContentAsBase64),读取器将抛出 NotSupportedException。
For this reader XDocument.CreateReader().CanReadBinaryContentis falsein contrast to the System.Xml.XmlNodeReader.
对于这位读者XDocument.CreateReader().CanReadBinaryContent是false相反的System.Xml.XmlNodeReader。
For example this program throws an exception:
例如这个程序抛出一个异常:
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)
}
}
}
However, extracting the XML as stringand passing it as TextReaderinto the serializer works:
但是,将 XML 提取为string并将其作为传递TextReader给序列化程序是有效的:
using (var reader = new StringReader(document.ToString()))
I would be interested as well if there is another way to deserialize an XDocumentthat includes binary data without converting it into a string first.
如果有另一种方法可以反序列化一个XDocument包含二进制数据的数据,而无需先将其转换为字符串,我也会感兴趣。
回答by KarmaEDV
I like @Simon_Weaver 's answer the best. Based on that this is my summary:
我最喜欢@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
}
}
回答by dotNetkow
Just thought I should add that after the XmlReader is created, i.e.:
只是想我应该在创建 XmlReader 之后添加,即:
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
XmlReader reader = xmlDocumentToDeserialize.CreateReader();
then you should call:
那么你应该打电话:
reader.MoveToContent();
because otherwise the reader will not "point" to the first node, causing the appearance of an empty reader! Then you can safely call Deserialize:
因为否则阅读器不会“指向”第一个节点,导致出现空阅读器!然后你可以安全地调用反序列化:
MyObject myObject = (MyObject)serializer.Deserialize(reader);

