Сериализация XML без утилизации - PullRequest
6 голосов
/ 18 мая 2009
       using (var file_stream = File.Create("users.xml"))
        {
            var serializer = new XmlSerializer(typeof(PasswordManager));
            serializer.Serialize(file_stream, this);
            file_stream.Close();
        }

Использование приведенного выше кода работает отлично. Однако, когда я сокращаю его до:

          var serializer = new XmlSerializer(typeof(PasswordManager));
          serializer.Serialize(File.Create("users.xml"), this);

Я получаю следующее исключение при попытке десериализации файла users.xml в том же тесте: Процесс не может получить доступ к файлу 'users.xml', поскольку он используется другим процессом.

Причина, по-видимому, в том, что метод File.Create возвращает открытый FileStream, который я не могу закрыть, так как не держу ссылку на него.

Мой плохой или Microsoft? ; -)

Ответы [ 4 ]

11 голосов
/ 18 мая 2009

Проблема в том, что во втором примере вы открываете дескриптор файла, который никогда не утилизируете, поэтому при втором вызове метода он выдаст исключение, которое вы описываете. Первый фрагмент является предпочтительным способом (вы можете удалить бит file_stream.Close () - он будет автоматически вызываться Stream.Dispose ()).

2 голосов
/ 29 июня 2009

Вы должны сериализоваться в блоке try finally , чтобы вы могли убедиться, что файл закрыт / удален независимо от успеха или неудачи. Это то, что , использующее ключевое слово , делает для вас.

var serializer = new XmlSerializer(typeof(PasswordManager));
var fs = File.Create("users.xml");
try { serializer.Serialize(fs,this); }
finally { fs.Close(); }
0 голосов
/ 30 июня 2009

File.Create должен быть размещен вне блока try, как показано в моем предыдущем ответе. Если вы поместите его внутрь блока try, вам нужно проверить fs на наличие нулевой ссылки перед закрытием. Ниже показан исправленный код, но мой первый ответ гораздо лучше, поскольку вы можете избежать этой проверки.

serializer = new XmlSerializer(typeof(PasswordManager));
FileStream fs;
try
{
    fs = File.Create("users.xml");
    serializer.Serialize(fs, this);
}
finally
{
    if (fs != null)  // in case File.Create fails
        fs.Close(); // or fs.Dispose()
}
0 голосов
/ 21 июня 2009

Если бы у вас не было оператора "using", но вы сохранили закрытие, с вами все было бы в порядке.

[Редактировать: Добавлена ​​попытка ... наконец, спасибо cheeso]

var serializer = new XmlSerializer(typeof(PasswordManager));
FileStream fs;
try
{
    fs = File.Create("users.xml");
    serializer.Serialize(fs, this);
}
finally
{
    fs.Close(); // or fs.Dispose()
}

В этом случае, однако, Dispose предпочтительнее, потому что он знает all действия, которые он должен выполнить для очистки, включая закрытие (и все остальное).

...