XPathDocument Stream closing

Today I encountered a really annoying documentation bug in the xml side of .net. Whenever you create an XPathDocument using the Stream based constructor, whenever the construction returns, your stream is closed.

                  documentStream = new MemoryStream();

                  XslFoEngine.CopyStream(message.BodyStream,documentStream);

                  documentStream.Position = 0;

                  XPathDocument document = new XPathDocument(documentStream); 

You wouldn’t expect the Stream to be closed, but it is. What is happening behind the scene is that the following constructors wrap whatever you throw at them with an XmlTextReader object, call the Init(XmlReader) method, which itself close the reader, in turn closing the stream.

Initializes a new instance of the XPathDocument class.

[Visual Basic] Public Sub New(Stream)

[C#]public XPathDocument(Stream);

[C++] public: XPathDocument(Stream*);

[JScript] public function XPathDocument(Stream);

Initializes a new instance of the XPathDocument class.

[Visual Basic] Public Sub New(String)

[C#]public XPathDocument(string);

[C++] public: XPathDocument(String*);

[JScript] public function XPathDocument(String);

Initializes a new instance of the XPathDocument class.

[Visual Basic] Public Sub New(TextReader)

[C#]public XPathDocument(TextReader);

[C++] public: XPathDocument(TextReader*);

[JScript] public function XPathDocument(TextReader);

Initializes a new instance of the XPathDocument class.

[Visual Basic] Public Sub New(XmlReader)

[C#]public XPathDocument(XmlReader);

[C++] public: XPathDocument(XmlReader*);

[JScript] public function XPathDocument(XmlReader);

Initializes a new instance of the XPathDocument class.

[Visual Basic] Public Sub New(String, XmlSpace)

[C#]public XPathDocument(string, XmlSpace);

Only way to go around the problem, create the reader yourself, but don’t close it.

                  documentStream = new MemoryStream();

                  XslFoEngine.CopyStream(message.BodyStream,documentStream);

                  documentStream.Position = 0;

                  XPathDocument document = new XPathDocument(new XmlTextReader(documentStream));

PS: I will respond to IanG comments on my ReaderWriterLock entry with some statistics later this week on when / how to use this pattern (high contention), as I fully agree with him that you shouldn’t just assume without testing. In this specific case, the contention is really high on a very high load long living threads environment. More on that later.

 

Ads