2013-10-13 73 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方法的開始,但我得到的東西是如何工作的深入的瞭解很有意思。

相關問題