2016-04-12 20 views
0

MemoryStream(XmlWriterによって書き込まれた)から読み取ろうとすると、 はObjectDisposedException ("Cannot access a closed Stream.")をスローします。ストリームへのシリアル化とストリームからの読み取り

'using'ステートメントの途中でXmlWriterを閉じると、スローせずにコードを返すことができます。ここで何か怪しいです。

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の両方で発生します。

周り読んだ後、私は直接、Jonの答えherereturn Encoding.UTF8.GetString(stream.GetBuffer(), 0, stream.Length);

ごとにメモリストリームから文字列を読むことができるしかし、最初に、私は例のコードで例外を引き起こすことが起こっているかを理解したいと思います。

答えて

-1

例コードが発揮されるという問題が二重処分(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'を' 'MemoryStream''に置くことができます。 –

+0

解決策を投稿してください。 2つのネストされた使用を使用する場合、ベースストリームを2回廃棄する例外が発生します。 私の質問に答えた唯一の理由は、元のコードスニペットでネストされた 'using'ステートメントを使用するときに何が問題を引き起こしているのかを明らかにすることでした。 – aitee

+0

コードが更新されました。 XmlWriterを破棄する場合でも。 MemoryStreamは、すでに閉じられているストリームに対してdisposeが呼び出されたときにスローされるので、usingに入れることはできません。 もっと良い解決策があれば、本当にありがとうございます。 ありがとう! – 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

私はそれを理解しています。しかし、近くにreader.ReadToEnd()をスローします。 これはこの質問についてです。 – aitee