2016-04-12 10 views
0

При попытке чтения из MemoryStream (который был написан XmlWriter), он выбрасывает ObjectDisposedException ("Cannot access a closed Stream.").Сериализация для потока, а затем чтение из потока

Я наткнулся на то, что закрытие XmlWriter в середине инструкции «using» позволяет коду возвращаться без металирования. Здесь что-то здесь.

public static string SerializeToString(T obj) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(T)); 

     using (var stream = new MemoryStream()) 
     using (var writer = XmlWriter.Create(stream)) 
     { 
      serializer.Serialize(writer, obj); 

      writer.Flush(); 
      // Swapping the flush for close fixes the ObjectDisposedException 
      //writer.Close(); 
      stream.Position = 0; 


      using (var reader = new StreamReader(stream)) 
      { 
       return reader.ReadToEnd(); 
      } 
     } 
    } 

Это происходит как для Silverlight, так и для .NET 4.5.

После прочтения вокруг я мог прочитать строку из потока памяти непосредственно в соответствии с ответом Джона herereturn Encoding.UTF8.GetString(stream.GetBuffer(), 0, stream.Length);

Но сначала я хотел бы понять, что происходит, чтобы вызвать исключение в коде примера.

ответ

-1

Вопрос о том, что пример кода проявляет двойная Утилизация (The StreamReader и XmlWriter и утилизировать их BaseStream [MemoryStream]).

Помещение StreamReader в верхний блок пользовательских настроек устраняет проблему.

Но в конце концов я не нужно StreamReader, чтобы получить текст, и пошел с следующее:

 public static string SerializeToString(T obj) 
     { 
      XmlSerializer serializer = new XmlSerializer(typeof(T)); 

      using (var memoryStream = new MemoryStream()) 
      using (var writer = XmlWriter.Create(memoryStream)) 
      { 
       serializer.Serialize(writer, obj); 
       return Encoding.UTF8.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length); 
      } 
     } 
+1

Очень плохая рекомендация - не следует - всегда располагайте объекты 'IDisposable'. Вы можете использовать 'MemoryStream.GetBuffer' и' MemoryStream.ToArray' на установленном 'MemoryStream', поскольку они существуют именно по этой причине. –

+0

Не могли бы вы предоставить вам решение? При использовании двух вложенных операций возникает исключение для одновременного удаления базового потока. Единственная причина, по которой я ответил на мой вопрос, состояла в том, чтобы попытаться пролить свет на то, что вызывает проблему, когда вы используете вложенные выражения «using» в исходном фрагменте кода. – aitee

+0

Код обновлен. Даже при утилизации XmlWriter. MemoryStream нельзя использовать в использовании, поскольку он бросает, когда утилита вызывается в уже закрытом потоке. Если у вас есть лучшее или более правильное решение, я был бы очень признателен, если бы вы пошли и опубликовали его. Спасибо! – aitee

1

Закрытие writer также будет Close() базовым объектом потока.

Вам не нужно явно закрывать запись, так как оператор using сделает это автоматически в конце блока.

using (var stream = new MemoryStream()) 
using (var writer = XmlWriter.Create(stream)) 
{  
    ... 
    //writer.Close(); <=== don't do this 
    ... 
} // <=== stream and writer get closed here 
+0

Я понимаю, что. Но без закрытия читатель.ReadToEnd() бросает. Вот о чем этот вопрос. – aitee