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

10 Окт
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.
Спасибо за внимание.
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх