zaterdag 7 maart 2009

Nice XmlWriter extender

Sometimes I just like to write some code. I try to think of something to make usage of framework parts even better. I remembered the burnden of writing and XML file using the XmlWriter class. Loosing track of all the WriteStartXXX and WriteEndXXX in a method can be hard to fix and Visual Studio removing any indenting when reformatting is accidently executed doesn't help.

I saw the Tracer class in the logging code block of the Enterprise Library. This class is supposed to be used in a using() { ... } constuction. The constructor takes care of starting the trace and when the object is disposed ending the trace is taken care of.

With this in mind and using my personal favorite feature: extension methods. I came up with the following:


public static class XmlWriterExtensions {

public abstract class XmlWriterWatcher : IDisposable
{
protected XmlWriter writer;
private bool disposed = false;

public XmlWriterWatcher(XmlWriter writer)
{
this.writer = writer;
}

protected abstract void CallWriteEndMethod();

#region IDisposable Members

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

public void Dispose(bool disposing)
{
if (!this.disposed)
{
// If disposing equals true, dispose all managed and unmanaged resources.
if (disposing)
{
CallWriteEndMethod();
writer = null;
}

// Call the appropriate methods to clean up
// unmanaged resources here.
}
disposed = true;
}

#endregion

~XmlWriterWatcher()
{
Dispose(false);
}
}

public class StartElementWatcher : XmlWriterWatcher
{
private bool useWriteFullElementEnd = false;

public StartElementWatcher(XmlWriter writer)
: base(writer)
{
}

public StartElementWatcher(XmlWriter writer, bool useWriteFullElementEnd)
: base(writer)
{
this.useWriteFullElementEnd = useWriteFullElementEnd;
}

protected override void CallWriteEndMethod()
{
if (useWriteFullElementEnd)
writer.WriteFullEndElement();
else
writer.WriteEndElement();
}

}

public class StartDocumentWatcher : XmlWriterWatcher
{
public StartDocumentWatcher(XmlWriter writer)
: base(writer)
{
}

protected override void CallWriteEndMethod()
{
writer.WriteEndDocument();
}
}

public class StartAttributeWatcher : XmlWriterWatcher
{
public StartAttributeWatcher(XmlWriter writer)
: base(writer)
{
}

protected override void CallWriteEndMethod()
{
writer.WriteEndAttribute();
}
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName)
{
writer.WriteStartElement(localName);
return new StartElementWatcher(writer);
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName, string ns)
{
writer.WriteStartElement(localName, ns);
return new StartElementWatcher(writer);
}

public static StartElementWatcher StartElement(this XmlWriter writer, string prefix, string localName, string ns)
{
writer.WriteStartElement(prefix, localName, ns);
return new StartElementWatcher(writer);
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName, bool useWriteFullEndElement)
{
writer.WriteStartElement(localName);
return new StartElementWatcher(writer, useWriteFullEndElement);
}

public static StartElementWatcher StartElement(this XmlWriter writer, string localName, string ns, bool useWriteFullEndElement)
{
writer.WriteStartElement(localName, ns);
return new StartElementWatcher(writer, useWriteFullEndElement);
}

public static StartElementWatcher StartElement(this XmlWriter writer, string prefix, string localName, string ns, bool useWriteFullEndElement)
{
writer.WriteStartElement(prefix, localName, ns);
return new StartElementWatcher(writer, useWriteFullEndElement);
}

public static StartDocumentWatcher StartDocument(this XmlWriter writer)
{
writer.WriteStartDocument();
return new StartDocumentWatcher(writer);
}

public static StartDocumentWatcher StartElement(this XmlWriter writer, bool standalone)
{
writer.WriteStartDocument(standalone);
return new StartDocumentWatcher(writer);
}

public static StartAttributeWatcher StartAttribute(this XmlWriter writer, string localName)
{
writer.WriteStartAttribute(localName);
return new StartAttributeWatcher(writer);
}

public static StartAttributeWatcher StartAttribute(this XmlWriter writer, string localName, string ns)
{
writer.WriteStartAttribute(localName, ns);
return new StartAttributeWatcher(writer);
}

public static StartAttributeWatcher StartAttribute(this XmlWriter writer, string prefix, string localName, string ns)
{
writer.WriteStartAttribute(prefix, localName, ns);
return new StartAttributeWatcher(writer);
}

}


Usage of this added feature to the XmlWriter would be as follows:


using (var w = XmlWriter.Create("D:\\Text.xml"))
{
using (w.StartDocument())
{
using (w.StartElement("TestElement"))
{
w.WriteString("test123");
}
}
}

Geen opmerkingen: