2013-10-13 6 views
2

XmlSerializer.Deserialize загружает весь документ в память перед конструированием целевого объекта?Выполняет ли XmlSerializer.Deserialize весь документ в памяти?

Содержимое XML происходит с клиентской стороны, на которую я не полностью доверяю. Поэтому я использую XmlReader для синтаксического анализа его в режиме «только вперед», не смотря на обратную сторону. Хотя XmlSerializer.Deserialize может десериализоваться из XmlReader, я не уверен, что он кэширует весь документ, который он читает из XmlReader, в память и, следовательно, создает давление памяти в систему. что будет нежелательным.

Я посмотрел на MSDN, но, похоже, это не упоминается. Я что-то пропустил?

+0

Я думаю, что это работа ОС. Он управляет этой проблемой механизмом поискового вызова. – Muctadir

+0

@MuctadirDinar: ** no **, ОС не имеет к этому никакого отношения, и он не спрашивает, когда бит находится в памяти; он спрашивает, когда бит анализируется в документе или наборе узлов, которые находятся в памяти. –

+0

Вам следует подумать о создании собственного класса, полученного из 'XmlReader'. Ваш класс мог просто игнорировать все, чего он не доверял, становясь источником надежной последовательности узлов для XML-сериализатора (или LINQ to XML) для потребления. –

ответ

1

Короткий ответ: Нет, это не так.

Я пришел сюда с точно таким же вопросом и был удивлен, что ответа не было. Во-первых, я подумал об испытании, но потом решил пойти глубже и увидеть его сам.
Итак, я потратил довольно много времени, чтобы изучить, как работает сериализация/десериализация, изучил исходный код .NET Framework и динамически генерируемую сборку.
Вот ключевые части кода с моими комментариями из моего небольшого расследования (незначительные части опущены).

Пусть дано:

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 метод реализован таким образом, но это было интересно для меня, чтобы получить более глубокие знания о том, как работают вещи.

Смежные вопросы