c# - ¿Hay alguna forma de cerrar un StreamWriter sin cerrar su BaseStream?
dispose (5)
.NET 4.5 tiene un nuevo método para eso!
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
)
Mi problema de raíz es que al using
llamadas Dispose
en un StreamWriter
, también BaseStream
el BaseStream
(el mismo problema con Close
).
Tengo una solución para esto, pero como puede ver, implica copiar la secuencia. ¿Hay alguna manera de hacer esto sin copiar la secuencia?
El propósito de esto es obtener el contenido de una cadena (originalmente leída desde una base de datos) en una secuencia, de modo que la secuencia pueda ser leída por un componente de un tercero.
NB : No puedo cambiar el componente de terceros.
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;
}
Usado como
public void Noddy()
{
System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
My3rdPartyComponent.ReadFromStream(myStream);
}
Idealmente, estoy buscando un método imaginario llamado BreakAssociationWithBaseStream
, por ejemplo
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;
}
La secuencia de memoria tiene una propiedad ToArray que puede usarse incluso cuando la transmisión está cerrada. Para Array, escribe los contenidos de la secuencia en una matriz de bytes, independientemente de la propiedad Posición. Puede crear una nueva transmisión según la secuencia en la que escribió.
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;
}
Necesita crear un descendiente de StreamWriter y anular su método de eliminación, al pasar siempre false al parámetro de eliminación, forzará al escritor de flujo a NO cerrarse, el StreamWriter simplemente llama a disponer en el método de cierre, por lo que no es necesario anularlo (por supuesto, puede agregar todos los constructores si lo desea, solo tengo uno):
public class NoCloseStreamWriter : StreamWriter
{
public NoCloseStreamWriter(Stream stream, Encoding encoding)
: base(stream, encoding)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(false);
}
}
Si está utilizando .NET Framework 4.5 o posterior, hay una sobrecarga de StreamWriter con la que puede solicitar que la secuencia base se deje abierta cuando se cierra el escritor .
En versiones anteriores de .NET Framework anteriores a la 4.5, StreamWriter
supone que posee la transmisión. Opciones:
- No deseche
StreamWriter
; simplemente enjuague. - Cree una envoltura de flujo que ignore las llamadas a
Close
/Dispose
pero proxies todo lo demás a lo largo. Tengo una implementación de eso en MiscUtil , si quieres capturarlo desde allí.
Simplemente no llame a Dispose
en el StreamWriter
. La razón por la cual esta clase es desechable no se debe a que contiene recursos no administrados, sino a permitir la eliminación de la secuencia, que a su vez podría contener recursos no administrados. Si la vida del flujo subyacente se maneja en otro lugar, no es necesario que se deshaga del escritor.