471,318 Members | 2,092 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,318 software developers and data experts.

Using XmlTextWriter without closing the base stream

I want to write a method that will accept a stream as a parameter, and which
will write xml to the stream (based in reality on database results) using
the XmlTextWriter class. However, this insists on closing my stream, and I
can't convince it not to.

A much-simplified example is below; basically, as soon as the writer is
disposed (marked **** below) the base stream gets closed - which is a pain
if I was still using it ;-p

The base XmlWriter class has a read-only Settings property which in turn has
a CloseOutput property; this would be fine, except Settings is null in the
following, so I can't get to an XmlSettings object to toggle this...

Is there any way to write to such a stream without it getting closed?

Thanks in advance,

Marc
using System;
using System.IO;
using System.Xml;
namespace ConsoleApplication1 {
public static class Program {
public static void Main() {
using (MemoryStream stream = new MemoryStream()) {
WriteXml(stream);
TestStream(stream); // fails - stream now closed on exit of
method
}
}
private static void TestStream(System.IO.Stream stream) {
Console.WriteLine(new string('=', 20));
try {
long position = stream.Position;
stream.Position = 0;
XmlDocument doc = new XmlDocument();
doc.Load(stream);
stream.Position = position;
Console.WriteLine(doc.OuterXml);
} catch (Exception e) {
Console.WriteLine(e); // absorb exception
}
}
public static void WriteXml(Stream stream) {
using (XmlTextWriter writer = new XmlTextWriter(stream, null)) {
writer.Formatting = Formatting.None;
writer.Namespaces = false;
writer.WriteStartElement("Xml");
writer.WriteStartElement("Element");
writer.WriteAttributeString("Attrib1", "Value1");
writer.WriteAttributeString("Attrib2", "Value2");
writer.WriteEndElement();
writer.WriteEndElement();
writer.Flush();
TestStream(writer.BaseStream); // works; stream still open
} // **** closes base stream
}
}
}
Feb 2 '06 #1
8 9835
Might have found it;

XmlWriter.Create

Marc
Feb 2 '06 #2
Thanks for replying; actually, I found that you can do this if you use one
of the overloads to XmlWriter.Create (which accepts the stream and a
settings object).

Marc
Feb 2 '06 #3
If you don't want things disposed then don't dispose of them - remove the
"using" statement from WriteXml.

It is poor design for a method to dispose of a resource that it didn't
acquire [except of course in the case where its job is explicitly defined to
be disposing of the resource].

Also,depending on your design, you should only dispose of either the base
stream or the wrapper - you are effectively trying to do both.

You do not need to explicitly dispose of an XmlTextWriter anywhere unless
you have dispensed with the base stream - garbage collection will handle it
perfectly well.

Finally a MemoryStream is the one type of Stream that does not need to be
disposed AT ALL because it is just managed memory although it is good style
to treat it like any other stream.
"Marc Gravell" <mg******@rm.com> wrote in message
news:%2****************@TK2MSFTNGP15.phx.gbl...
I want to write a method that will accept a stream as a parameter, and
which will write xml to the stream (based in reality on database results)
using the XmlTextWriter class. However, this insists on closing my stream,
and I can't convince it not to.

A much-simplified example is below; basically, as soon as the writer is
disposed (marked **** below) the base stream gets closed - which is a pain
if I was still using it ;-p

The base XmlWriter class has a read-only Settings property which in turn
has a CloseOutput property; this would be fine, except Settings is null in
the following, so I can't get to an XmlSettings object to toggle this...

Is there any way to write to such a stream without it getting closed?

Thanks in advance,

Marc
using System;
using System.IO;
using System.Xml;
namespace ConsoleApplication1 {
public static class Program {
public static void Main() {
using (MemoryStream stream = new MemoryStream()) {
WriteXml(stream);
TestStream(stream); // fails - stream now closed on exit of
method
}
}
private static void TestStream(System.IO.Stream stream) {
Console.WriteLine(new string('=', 20));
try {
long position = stream.Position;
stream.Position = 0;
XmlDocument doc = new XmlDocument();
doc.Load(stream);
stream.Position = position;
Console.WriteLine(doc.OuterXml);
} catch (Exception e) {
Console.WriteLine(e); // absorb exception
}
}
public static void WriteXml(Stream stream) {
using (XmlTextWriter writer = new XmlTextWriter(stream, null))
{
writer.Formatting = Formatting.None;
writer.Namespaces = false;
writer.WriteStartElement("Xml");
writer.WriteStartElement("Element");
writer.WriteAttributeString("Attrib1", "Value1");
writer.WriteAttributeString("Attrib2", "Value2");
writer.WriteEndElement();
writer.WriteEndElement();
writer.Flush();
TestStream(writer.BaseStream); // works; stream still open
} // **** closes base stream
}
}
}

Feb 2 '06 #4
I know what you are saying, and I am glad that I have found a resolution -
however, I'm not quite sure that I agree with all of your points:

Forgetting about streams and writers; if I have an object that is a:
disposable and b: I feel ownership for (in particular if I explicitely
created it), then my instinct tells me that I should dispose of that object.
Due to encapsulation, it isn't necessarily my business to know *exactly*
what is going on under the hood, for instance it could be using a windows
handle, a file, a database resource etc - not my problem.

So:

If I create a class (that happens to be called a stream), should I dispose
it when I am done? I think I should.
If I create a class (that happens to be called a writer, and which uses a
stream), should I still dispose it when I am done? I think I should.
Likewise with the memory stream; technically we know it doesn't need to be,
but that knowledge breaks the black-box rule of encapsulation.

For all I know, the implementation of either the stream or writer
(separately) could involve 17 other disposable / unmanaged objects (in
addition to my stream in the case of the writer), and I would like them to
be cleaned up properly and ASAP; I just don't want it to (necessarily)
dispose of an object that I am still using it just because it knows where it
is.

The main exceptions I can think of to scoped disposal are where I want one
to live longer than its natural scope (i.e. as a return value), but in my
example both entities were tightly scoped in a nested manner. It seems
logical to me to dispose of both of them in turn. Saying "ahh, but its a
stream, so only dispose of it at one level" pollutes things quite a bit to
my mind.

Anyway - I'm happy to disagree, and I'm happy (for this nested usage) to use
a ctor that lets me do this. And I really can see what you are saying about
other uses - I'm just saying that it should be up to me (which, it turns
out, it is). Other examples of more-conveniently handled wrappers are the
compression classes - these take a boolean on an overloaded ctor to let you
tell it "do you want me to close your stream for you?" - and yes, most of
the time you might.

Cheers for the input,

Marc
Feb 2 '06 #5
Marc Gravell wrote:

<snip>
Forgetting about streams and writers; if I have an object that is a:
disposable and b: I feel ownership for (in particular if I explicitely
created it), then my instinct tells me that I should dispose of that object.
Due to encapsulation, it isn't necessarily my business to know *exactly*
what is going on under the hood, for instance it could be using a windows
handle, a file, a database resource etc - not my problem.


<snip>

I entirely agree. I have my own class which might help you with further
such issues:
NonClosingStreamWrapper, which is in my miscellaneous utility library
(although I note I don't mention it on the front page,
unfortunately...)

http://www.pobox.com/~skeet/csharp/miscutil/

Jon

Feb 2 '06 #6
A handy wrapper class; next time I have such an issue (and can't find a
suitable ctor, which is probably the best solution in that it keeps things
simple) I may well make use of this.

Cheers,

Marc
Feb 2 '06 #7

"Marc Gravell" <mg******@rm.com> wrote in message
news:uj**************@TK2MSFTNGP14.phx.gbl...
I know what you are saying, and I am glad that I have found a resolution -
however, I'm not quite sure that I agree with all of your points:

Forgetting about streams and writers; if I have an object that is a:
disposable and b: I feel ownership for (in particular if I explicitely
created it), then my instinct tells me that I should dispose of that
object. Due to encapsulation, it isn't necessarily my business to know
*exactly* what is going on under the hood, for instance it could be using
a windows handle, a file, a database resource etc - not my problem.

So:

If I create a class (that happens to be called a stream), should I dispose
it when I am done? I think I should.
Agreed.
If I create a class (that happens to be called a writer, and which uses a
stream), should I still dispose it when I am done? I think I should.
No - because it uses the stream - it doesn't own it and it doesn't own
anything that needs disposing so it shouldn't be disposed.
Likewise with the memory stream; technically we know it doesn't need to
be, but that knowledge breaks the black-box rule of encapsulation.
That's why I said that good practice would be to dispose of it anyway.
For all I know, the implementation of either the stream or writer
(separately) could involve 17 other disposable / unmanaged objects (in
addition to my stream in the case of the writer), and I would like them to
I think it is quite clear the the writer only implements IDisposable so as
to close the stream.

For the reason that you give it would be very bad practice to have a class
own one resource but just use another.
be cleaned up properly and ASAP; I just don't want it to (necessarily)
dispose of an object that I am still using it just because it knows where
it is.

The main exceptions I can think of to scoped disposal are where I want one
to live longer than its natural scope (i.e. as a return value), but in my
example both entities were tightly scoped in a nested manner. It seems
logical to me to dispose of both of them in turn. Saying "ahh, but its a
stream, so only dispose of it at one level" pollutes things quite a bit to
my mind.
I agree that you can make a case for XmlTextWriter not implementing
IDisposable but I suppose that it is just too useful in the common case
where the stream is a file.
Anyway - I'm happy to disagree, and I'm happy (for this nested usage) to
use a ctor that lets me do this. And I really can see what you are saying
about other uses - I'm just saying that it should be up to me (which, it
turns out, it is). Other examples of more-conveniently handled wrappers
are the compression classes - these take a boolean on an overloaded ctor
to let you tell it "do you want me to close your stream for you?" - and
yes, most of the time you might.


I think that I'd probably agree though that that is the best solution
although a bit ugly. It is just one of the many unfortunate examples of
different practices used in different parts of the framework.
Feb 2 '06 #8
Nick Hounsome <nh***@nickhounsome.me.uk> wrote:
If I create a class (that happens to be called a writer, and which uses a
stream), should I still dispose it when I am done? I think I should.
No - because it uses the stream - it doesn't own it and it doesn't own
anything that needs disposing so it shouldn't be disposed.


How do you know that it (the created instance) doesn't have *other*
things which need to be disposed though?
Likewise with the memory stream; technically we know it doesn't need to
be, but that knowledge breaks the black-box rule of encapsulation.


That's why I said that good practice would be to dispose of it anyway.
For all I know, the implementation of either the stream or writer
(separately) could involve 17 other disposable / unmanaged objects (in
addition to my stream in the case of the writer), and I would like them to


I think it is quite clear the the writer only implements IDisposable so as
to close the stream.


If we're going to go by what's "quite clear" then I don't see that it's
good practice to dispose of a MemoryStream, as it's "quite clear" that
that doesn't have any other resources. Going by intuition is a bad idea
in this kind of thing, IMO.
For the reason that you give it would be very bad practice to have a class
own one resource but just use another.


But that could certainly be the situation in some cases. In those
cases. In those cases, I believe the API should allow you to specify
which resources are effectively owned by the class you're passing them
to, and which resources are owned by the caller.

<snip>
Anyway - I'm happy to disagree, and I'm happy (for this nested usage) to
use a ctor that lets me do this. And I really can see what you are saying
about other uses - I'm just saying that it should be up to me (which, it
turns out, it is). Other examples of more-conveniently handled wrappers
are the compression classes - these take a boolean on an overloaded ctor
to let you tell it "do you want me to close your stream for you?" - and
yes, most of the time you might.


I think that I'd probably agree though that that is the best solution
although a bit ugly. It is just one of the many unfortunate examples of
different practices used in different parts of the framework.


I don't see it as ugly particularly - it's just a matter of telling the
API what it owns and what it doesn't own. In some cases it will be
useful for the new object to own the resource, in some cases not.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 2 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Magnus | last post: by
1 post views Thread by Terrence Chan | last post: by
2 posts views Thread by theinsanecoder | last post: by
2 posts views Thread by Random | last post: by
3 posts views Thread by GaryDean | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.