Question

Does XmlSerializer.Deserialize load the entire document in memory before constructing the target object?

The content of the XML is coming from client side which I don't fully trust. Therefore I'm using XmlReader to parse it in a forward-only, non-looking-back fashion. Although XmlSerializer.Deserialize can deserialize from XmlReader, what I'm not sure is that whether it caches the entire document it reads from XmlReader into memory and therefore poses memory pressure to the system. which will be undesirable.

I looked at the MSDN, but it doesn't seem to mention it. Am I missing anything?

Était-ce utile?

La solution

Short answer: No, it doesn't.

I came here with exactly the same question and was surprised that there were no answer. Firstly, I had thought about test, but then I decided to go deeper and see it myself.
So I've spent quite some time to study how does serialization/deserialization work, explored .NET Framework source code and dynamically generated assembly.
Here are the key code parts with my comments from my little investigation (insignificant parts omitted).

Suppose we given:

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

After that we would get to this XmlSerializer class method:

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

Which leads us to:

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();
    }
}

Dynamically generated code looks like:

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 from XmlReader certainly looks like:

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;
}

Certainly, it was obvious from the beginning that Deserialize method implemented in such way, but it was interesting for me to get deeper knowledge of how things work.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top