Mon problème racine est que lorsque using
appelle Dispose
sur un StreamWriter
, il dispose également du BaseStream
(même problème avec Close
).
J'ai une solution pour cela, mais comme vous pouvez le voir, cela implique de copier le flux. Existe-t-il un moyen de le faire sans copier le flux?
Le but de ceci est d'obtenir le contenu d'une chaîne (initialement lue dans une base de données) dans un flux, afin que le flux puisse être lu par un composant tiers.
NB : Je ne peux pas changer le composant tiers.
public System.IO.Stream CreateStream(string value)
{
var baseStream = new System.IO.MemoryStream();
var baseCopy = new System.IO.MemoryStream();
using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
{
writer.Write(value);
writer.Flush();
baseStream.WriteTo(baseCopy);
}
baseCopy.Seek(0, System.IO.SeekOrigin.Begin);
return baseCopy;
}
Utilisé comme
public void Noddy()
{
System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
My3rdPartyComponent.ReadFromStream(myStream);
}
Idéalement, je recherche une méthode imaginaire appelée BreakAssociationWithBaseStream
, par exemple.
public System.IO.Stream CreateStream_Alternate(string value)
{
var baseStream = new System.IO.MemoryStream();
using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
{
writer.Write(value);
writer.Flush();
writer.BreakAssociationWithBaseStream();
}
return baseStream;
}
Si vous utilisez .NET Framework 4.5 ou version ultérieure, il existe une surcharge StreamWriter à l'aide de laquelle vous pouvez demander que le flux de base reste ouvert lorsque le programme d'écriture est fermé .
Dans les versions antérieures de .NET Framework antérieures à 4.5, StreamWriter
suppose qu'il possède le flux. Options:
StreamWriter
; rincez-le.Close
/Dispose
mais procède à tout le reste par procuration. J'ai une implémentation de cela dans MiscUtil , si vous voulez l'attraper à partir de là..NET 4.5 a une nouvelle méthode pour ça!
http://msdn.Microsoft.com/EN-US/library/gg712853 (v = VS.110, d = hv.2) .aspx
public StreamWriter(
Stream stream,
Encoding encoding,
int bufferSize,
bool leaveOpen
)
N'appelez simplement pas Dispose
sur le StreamWriter
. La raison pour laquelle cette classe est jetable n'est pas parce qu'elle contient des ressources non gérées, mais pour permettre l'élimination du flux qui lui-même pourrait contenir des ressources non gérées. Si la durée de vie du flux sous-jacent est gérée ailleurs, pas besoin de disposer du rédacteur.
Le flux de mémoire a une propriété ToArray qui peut être utilisée même lorsque le flux est fermé. To Array écrit le contenu du flux dans un tableau d'octets, quelle que soit la propriété Position. Vous pouvez créer un nouveau flux en fonction du flux dans lequel vous avez écrit.
public System.IO.Stream CreateStream(string value)
{
var baseStream = new System.IO.MemoryStream();
var baseCopy = new System.IO.MemoryStream();
using (var writer = new System.IO.StreamWriter(baseStream, System.Text.Encoding.UTF8))
{
writer.Write(value);
writer.Flush();
baseStream.WriteTo(baseCopy);
}
var returnStream = new System.IO.MemoryStream( baseCopy.ToArray());
return returnStream;
}
Vous devez créer un descendant de StreamWriter et remplacer sa méthode d'élimination, en passant toujours false au paramètre de suppression, cela forcera l'écrivain de flux à ne pas se fermer, le StreamWriter appelle simplement dispose dans la méthode close, il n'est donc pas nécessaire de le remplacer (bien sûr, vous pouvez ajouter tous les constructeurs si vous le souhaitez, je n'en ai qu'un):
public class NoCloseStreamWriter : StreamWriter
{
public NoCloseStreamWriter(Stream stream, Encoding encoding)
: base(stream, encoding)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(false);
}
}