Использование вложенных IDisposable объектов

26 июля 2011 г.

Я бы хотел рассказать о моем маленьком эксперименте с использованием вложенных (паттерн Decorator) System.IDisposable объектов на примере с System.Xml.XmlReader и System.IO.FileStream. О том, как грамотно, на мой взгляд, использовать их изложено под катом.

Поставим банальную задачу: создать метод порождающий объект класса System.Xml.XmlDocument с данными, загруженными из файла «test.xml» (Опустим содержимое файла и структуру Xml). Данную задачу можно сделать очень просто, используя метод Load(string filename) класса XmlDocument, но у нас тема про использование вложенных IDisposable объектов, поэтому сделаем это с помощью того же метода, но принимающего в качестве параметра объект класса System.Xml.XmlReader.

Для этого нам нужно создать объект класса FileStream. Затем создать объект класса XmlReader и вызвать метод Load, передав в него созданный объект. И вернуть созданный XmlDocument. Создать XmlReader можно двумя подходами: статический метод Create или создание реализации Syste.Xml.XmlTextReader. Кусочек кода:

XmlDocument GetXmlDocument()
{
using (XmlReader xmlReader = XmlReader.Create(new FileStream("test.xml")))
{
var xmlDocument = new XmlDocument();
xmlDocument.Load(xmlReader);
return xmlDocument;
}
}

В принципе, код без ошибок?

А вот и нет. После наблюдений в режиме отладчика, оказалось, что у объекта класса FileStream метод Dispose не вызывается после выхода из блока с using. Кстати, созданный объект методом Create — не объект класса XmlTextReader.

Тогда я решил воспользоваться созданием экземпляра XmlTextReader.
Кусочек кода

XmlReader.Create(new FileStream("test.xml"))

меняем на

new XmlTextReader(new FileStream("test.xml"))

Теперь все работает (оба объекта освобождают ресурсы после выхода из блока using). Проверял на .NET 4.0.

О чем пост? О том, что нужно аккуратно использовать такие конструкции.

Использование декорированных конструкций было результатом изучения Java с ее системой ввода-вывода, где много построено на паттерне Decorator, а также попытка ухода от спагетти-кода с использованием множества вложенных using и try/catch.

Про интерфейс IDisposable изложено много, но на всякий случай: System.IDisposable в MSDN.

Теги:
рубрика Программирование
  • Похожие статьи
  • Предыдущие из рубрики