【问题标题】:Does XmlSerializer.Deserialize load the entire document in memory?XmlSerializer.Deserialize 是否将整个文档加载到内存中?
【发布时间】:2013-10-13 20:41:00
【问题描述】:

XmlSerializer.Deserialize 是否在构造目标对象之前将整个文档加载到内存中?

XML 的内容来自我不完全信任的客户端。因此,我使用 XmlReader 以仅向前、不可回溯的方式对其进行解析。虽然XmlSerializer.Deserialize 可以从 XmlReader 反序列化,但我不确定它是否将从 XmlReader 读取的整个文档缓存到内存中,从而对系统造成内存压力。这将是不可取的。

我查看了 MSDN,但似乎没有提及。我错过了什么吗?

【问题讨论】:

  • 我认为这是操作系统的工作。它通过分页机制管理这个问题。
  • @MuctadirDinar:,操作系统与此无关,他并没有询问这些位何时在内存中;他在询问这些位何时被解析为内存中的文档或节点集。
  • @JohnSaunders 实现我自己的 XmlReader 在这里没有帮助。 .Net XmlReader 已经是串行的。但是我的问题是,使用 XmlReader 底层的 XmlSerializer 是否会将整个文档加载到内存中,然后 then 进行反序列化。我个人认为不是这样,但是通过查看MSDN,我无法确认,我也没有办法通过测试来验证。
  • 否,因为 XmlSerialize 仍然可能缓存读取器传递给它的所有内容。如果有大量这样的数据,XmlSerializer本质上是在内存中保存了大量的数据,因此会给服务器带来内存压力。这归结为 .NET 如何实现 Xmlserializer,这就是我寻找 MSDN 以寻求答案的原因。但是好像没有。
  • 制作一个庞大的Xml文档并传入测试它!

标签: c# .net xml deserialization xmlserializer


【解决方案1】:

简答:不,不是。

我带着完全相同的问题来到这里,并很惊讶没有答案。 首先,我曾考虑过测试,但后来我决定深入了解一下。
所以我花了相当长的时间研究序列化/反序列化是如何工作的,探索了 .NET Framework 源代码和动态生成的程序集。
以下是我的小调查中我的 cmets 的关键代码部分(省略了无关紧要的部分)。

假设我们给出:

using (StreamReader reader = new StreamReader(filepath))
{
    var foobars = (List<Foobar>)serializer.Deserialize(reader);
}

之后我们会得到这个XmlSerializer类方法:

public object Deserialize(TextReader textReader) 
{ 
    XmlTextReader xmlReader = new XmlTextReader(textReader);
    return Deserialize(xmlReader, null); 
}

这导致我们:

public object Deserialize(XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
{
    // instantiate specific for our class Reader 
    // from dynamically generated assembly
    XmlSerializationReader reader = CreateReader(); 
    reader.Init(xmlReader, events, encodingStyle, tempAssembly); 
    try { 
        //call dynamically generated for out particular type method
        return Deserialize(reader);
    } 
    finally {
        reader.Dispose();
    }
}

动态生成的代码如下:

public class XmlSerializationReaderList1 : XmlSerializationReader
{
    protected override object Deserialize(XmlSerializationReader reader)
    {
        return ((XmlSerializationReaderList1) reader).Read3_ArrayOfFoobar();
    }

    // this is the method which do all work, huge part of it is omitted
    public object Read3_ArrayOfFoobar()
    {
        // this.Reader is XmlSerializationReader field of type XmlReader
        this.Reader.ReadStartElement();
        int num2 = (int) this.Reader.MoveToContent();
        int whileIterations = 0;
        int readerCount = this.ReaderCount;
        while ((this.Reader.NodeType == XmlNodeType.EndElement ? 0 : (this.Reader.NodeType != XmlNodeType.None ? 1 : 0)) != 0)
        {
            if (this.Reader.NodeType == XmlNodeType.Element)
            {
            if ((this.Reader.LocalName != this.id3_Foobar ? 0 : (this.Reader.NamespaceURI == this.id2_Item ? 1 : 0)) != 0)
            {
                if (list == null)
                this.Reader.Skip();
                else
                list.Add(this.Read2_Foobar(true, true));
            }
            else
                this.UnknownNode((object) null, ":Foobar");
            }
            else
            this.UnknownNode((object) null, ":Foobar");
            int num3 = (int) this.Reader.MoveToContent();
            this.CheckReaderCount
    }

    private Foobar Read2_Foobar(bool isNullable, bool checkType) { //... }
}

MoveToContent 来自XmlReader 肯定看起来像:

public virtual XmlNodeType MoveToContent()
{
  do
  {
    switch (this.NodeType)
    {
      case XmlNodeType.Element:
      case XmlNodeType.Text:
      case XmlNodeType.CDATA:
      case XmlNodeType.EntityReference:
      case XmlNodeType.EndElement:
      case XmlNodeType.EndEntity:
        return this.NodeType;
      case XmlNodeType.Attribute:
        this.MoveToElement();
        goto case XmlNodeType.Element;
      default:
        continue;
    }
  }
  while (this.Read());
  return this.NodeType;
}

当然,从一开始就很明显Deserialize 方法是以这种方式实现的,但对我来说更深入地了解事物的工作原理对我来说很有趣。

【讨论】:

    猜你喜欢
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 2018-01-07
    • 2020-07-24
    • 2016-11-03
    相关资源
    最近更新 更多