I was writing some code Friday, and I realized I was working with three
of my favorite namespaces all at once: System.IO, System.Xml, and System.Diagnositcs.
Most people will have used all of these namespaces at least once, but there are a
bunch of hidden gems that not everyone will have seen.
The task I was trying to pull off was to dump an XML document for debugging
purposes. I wanted to send it both to the console and to a logfile, to give me a real-time
idea of what was going on as well as a permanent record I could go back and analyze
The ability to write a piece of information to more than one place
for diagnostic purposes just cries out for System.Diagnostics.Trace.
So I started my program off with the following lines of code:
public class App
public static void Main()
string logfile =
which sets it up so that any time I call Trace.WriteLine,
a piece of text is written both to the command console and to a logfile whose name
is derived from the current date and time. The overload of ToString that
lets you specify the exact format for the date and time is pretty cool, I think.
Later, when I wanted to actually dump the XML, I did this:
StringWriter sw = new StringWriter();
XmlTextWriter wtr = new XmlTextWriter(sw);
wtr.Formatting = Formatting.Indented;
where xml is the XmlDocument that
I wanted to dump out.
There are a number of cool things in these few lines of code:
· The StringWriter class
give you a stream that you can use anywhere you’d use a normal TextWriter (e.g.
the constructor of XmlTextWriter),
but it writes to an internally maintained StringBuilder instead.
· The Formatting property
of XmlTextWriter to get that nice “every
nested element gets indented one level” look. Makes for much more readable output.
course, the call to Trace.WriteLine to
actually spew this same XML to more than once place.
A few caveats:
need to define the symbol TRACE in your build (Project Properties->Configuration
Properties->Build->Conditional Compilation Constants – just type in TRACE)
or Trace.WriteLine will not even make
it into the compiled program.
found that I needed to go through and flush each trace listener independently, or
my log file would get truncated. That was easy, though: just a foreach loop over the Trace.Listeners collection,
calling Flush and Close on