2016-04-12 2 views
0

Lors de la tentative de lecture à partir d'un MemoryStream (qui a été écrit par un XmlWriter), il lance un ObjectDisposedException ("Cannot access a closed Stream."). Je suis tombé sur le fait que la fermeture de XmlWriter au milieu de l'instruction 'using' permet au code de retourner sans lancer. Quelque chose est louche ici.Sérialisation pour diffuser puis lire à partir du flux

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(); 
      } 
     } 
    } 

Cela se produit pour Silverlight et .NET 4.5.

Après avoir lu autour je pouvais lire une chaîne à partir du flux de mémoire directement par la réponse de Jon herereturn Encoding.UTF8.GetString(stream.GetBuffer(), 0, stream.Length);

Mais d'abord je voudrais comprendre ce qui se passe à faire l'exception dans le code exemple.

Répondre

-1

La question que le code exemple expose est le double de rebut (StreamReader et XmlWriter à la fois disposer de leur BaseStream [MemoryStream]).

Mettre StreamReader dans le bloc supérieur des utilisations résout le problème.

Mais à la fin, je ne l'ai pas besoin de StreamReader pour obtenir le texte et je suis allé sur ce qui suit:

 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

Très mauvaise recommandation - ne pas suivre - toujours disposer des objets 'IDisposable'. Vous pouvez utiliser 'MemoryStream.GetBuffer' et' MemoryStream.ToArray' sur 'MemoryStream' disposé comme ils existent exactement pour cette raison. –

+0

Pouvez-vous s'il vous plaît poster votre solution? Lorsque vous utilisez deux utilisations imbriquées, une exception se produit pour disposer le flux de base deux fois. La seule raison pour laquelle j'ai répondu à ma question était d'essayer de faire la lumière sur l'origine du problème lors de l'utilisation des instructions 'using' imbriquées dans l'extrait de code original. – aitee

+0

Le code a été mis à jour. Même en disposant du XmlWriter. Le MemoryStream ne peut pas être mis dans l'utilisation comme il se déclenche quand la disposition est appelée sur un flux déjà fermé. Si vous avez une solution meilleure ou plus correcte, j'apprécierais vraiment si vous aviez l'intention de le publier. Merci! – aitee

1

La fermeture du writer va également Close() l'objet de flux sous-jacent.

Vous n'avez pas besoin de fermer explicitement le writer, car l'instruction using le fera automatiquement pour vous à la fin du bloc.

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

Je comprends. Mais sans fermer le lecteur. ReadToEnd() jette. Voilà de quoi parle cette question. – aitee