2013-10-13 46 views
2

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

XML的内容来自客户端,我不完全信任。因此,我正在使用XmlReader以前瞻性,非回顾性的方式解析它。尽管XmlSerializer.Deserialize可以从XmlReader反序列化,但我不确定是否将从XmlReader读取的整个文档缓存到内存中,因此会给系统带来内存压力。这将是不希望的。

我看着MSDN,但似乎没有提到它。我错过了什么?

+0

我认为这是OS的工作。它用分页机制来管理这个问题。 – Muctadir

+0

@MuadadirDinar:**没有**,操作系统与它无关,而且他没有询问这些位在内存中的位置;他问的是位何时被解析成一个文档或一组存储器中的节点。 –

+0

你应该考虑创建你自己的从'XmlReader'派生的类。您的类可以简单地忽略它不信任的任何东西,从而成为XML序列化程序(或LINQ to XML)消耗的可信序列节点的源。 –

回答

1

简短回答:不,它不。

我来到这里完全一样的问题,并感到惊讶,没有答案。 首先,我曾经考虑过测试,但后来我决定深入并亲自看看。
所以我花了相当一段时间来研究序列化/反序列化如何工作,探索了.NET框架源代码和动态生成的程序集。
下面是关键的代码部分与我的小调查评论(无关紧要的部分省略)。

假设我们给出:

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) { //... } 
} 

MoveToContentXmlReader肯定是这样的:

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方法的开始,但我得到的东西是如何工作的深入的了解很有意思。

相关问题