Mi problema principal es que cuando using
llama Dispose
a a StreamWriter
, también elimina el BaseStream
(mismo problema con Close
).
Tengo una solución para esto, pero como puede ver, implica copiar la transmisión. ¿Hay alguna forma de hacer esto sin copiar la transmisión?
El propósito de esto es obtener el contenido de una cadena (originalmente leída de una base de datos) en una secuencia, para que la secuencia pueda ser leída por un componente de terceros.
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;
}
Respuestas:
Si está utilizando .NET Framework 4.5 o posterior, existe una sobrecarga de StreamWriter mediante la cual puede solicitar que la secuencia base se deje abierta cuando se cierre el escritor .
En versiones anteriores de .NET Framework anteriores a la 4.5, se
StreamWriter
asume que posee la transmisión. Opciones:StreamWriter
; simplemente enjuague.Close
/Dispose
pero haga proxy de todo lo demás. Tengo una implementación de eso en MiscUtil , si quieres tomarlo desde allí.fuente
leaveOpen
parámetro después de queStreamWriter
se creó?Dispose
. La terminación del método no hace eso automáticamente. Es posible que se finalice más tarde si tiene un finalizador, pero eso no es lo mismo, y aún no está claro qué peligro está anticipando. Si cree que no es seguro devolver unStreamWriter
de un método porque el GC podría eliminarlo automáticamente, eso no es cierto.StreamWriter
no tiene un finalizador, no esperaría que lo tuviera, precisamente por esta razón.¡.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
fuente
bufferSize
es1024
. Los detalles están aquí .Simplemente no llame
Dispose
alStreamWriter
. La razón por la que esta clase es desechable no es porque contenga recursos no administrados, sino para permitir la eliminación de la secuencia que en sí misma podría contener recursos no administrados. Si la vida de la secuencia subyacente se maneja en otro lugar, no es necesario deshacerse del escritor.fuente
Flush
haría el trabajo llamar en caso de que almacenara datos?El flujo de memoria tiene una propiedad ToArray que se puede usar incluso cuando el flujo está cerrado. To Array escribe el contenido de la secuencia en una matriz de bytes, independientemente de la propiedad Position. Puede crear una nueva transmisión basada en la transmisión en la que escribió.
fuente
Stream.Position
puede no ser llamado después de que se dispone.Necesita crear un descendiente de StreamWriter y anular su método de disposición, pasando siempre falso al parámetro de disposición, obligará al escritor de flujo a NO cerrarse, StreamWriter solo llama a dispose en el método de cierre, por lo que no es necesario anúlelo (por supuesto, puede agregar todos los constructores si lo desea, solo tengo uno):
fuente
disposing
bandera es parte de laIDisposable
patrón . Pasar siemprefalse
alDispose(bool)
método de la clase base básicamente le indicaStreamWriter
que se está llamando desde el finalizador (que no es así cuando se llamaDispose()
explícitamente) y, por lo tanto, no debería acceder a ningún objeto administrado. Esto es por lo que no se deshará la corriente de base. Sin embargo, la forma en que lo ha logrado es un truco; ¡Sería mucho más sencillo simplemente no llamarDispose
en primer lugar!OwnedStream
, que ignoraDispose(bool)
yClose
).