Я начал использовать классы, реализующие IDisposable, для записи блоков в потоки с оператором using. Это полезно для сохранения правильного размещения и предотвращения отсутствия или неправильного размещения начальных/конечных частей.
По сути, конструктор записывает начало блока (например, открывающий XML-тег), Dispose() — конец (например, закрывающий XML-тег). Примером является UsableXmlElement ниже (он предназначен для больших XML-файлов, поэтому LINQ to XML или XmlDocument в памяти не являются вариантами).
Однако эти IDisposable не реализуют сложный шаблон, рекомендованный Microsoft, с деструктором/финализатором, отдельным методом Dispose(bool) и GC.SuppressFinalize(). Dispose просто записывает конечный элемент, и все.
Есть ли в этом какая-то обратная сторона или это хороший способ поддерживать правильное вложение элементов?
class UsableXmlElement : IDisposable
{
private XmlWriter _xwriter;
public UsableXmlElement(string name, XmlWriter xmlWriter)
{
_xwriter = xmlWriter;
_xwriter.WriteStartElement(name);
}
public void WriteAttribute<T>(string name, T value)
{
_xwriter.WriteStartAttribute(name);
_xwriter.WriteValue(value);
_xwriter.WriteEndAttribute();
}
public void WriteValue<T>(T value)
{
_xwriter.WriteValue(value);
}
public void Dispose()
{
_xwriter.WriteEndElement();
}
}
Использование выглядит следующим образом:
var xWriter = new XmlWriter(...)
using(var rootElement = new UsableXmlElement("RootElement", xWriter)
{
rootElement.WriteAttribute("DocVersion", 123)
using(var innerElement = new UsableXmlElement("InnerElement", xwriter)
{
// write anything inside Inner element
}
}
Результат:
<RootElement DocVersion="123">
<InnerElement>
<!-- anything -->
</InnerElement>
</RootElement>