Akar masalah saya adalah ketika using
memanggil Dispose
a StreamWriter
, itu juga membuang BaseStream
(masalah yang sama dengan Close
).
Saya memiliki solusi untuk ini, tetapi seperti yang Anda lihat, ini melibatkan penyalinan aliran. Adakah cara untuk melakukan ini tanpa menyalin aliran?
Tujuannya adalah untuk memasukkan konten string (aslinya dibaca dari database) ke dalam aliran, sehingga aliran dapat dibaca oleh komponen pihak ketiga.
NB : Saya tidak dapat mengubah komponen pihak ketiga.
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;
}
Digunakan sebagai
public void Noddy()
{
System.IO.Stream myStream = CreateStream("The contents of this string are unimportant");
My3rdPartyComponent.ReadFromStream(myStream);
}
Idealnya, saya mencari metode imajiner yang disebut BreakAssociationWithBaseStream
, mis
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;
}
Jawaban:
Jika Anda menggunakan .NET Framework 4.5 atau yang lebih baru, ada kelebihan StreamWriter yang dapat digunakan untuk meminta aliran dasar dibiarkan terbuka saat penulis ditutup .
Di versi .NETFramework sebelum 4.5,
StreamWriter
menganggapnya memiliki aliran. Pilihan:StreamWriter
; siram saja.Close
/Dispose
tetapi menjadi proxy yang lainnya. Saya memiliki implementasi itu di MiscUtil , jika Anda ingin mengambilnya dari sana.sumber
leaveOpen
parameterStreamWriter
itu setelah dibuat?Dispose
. Metode berakhir tidak melakukannya secara otomatis. Ini dapat diselesaikan nanti jika memiliki finalizer, tetapi itu bukan hal yang sama - dan masih belum jelas bahaya apa yang Anda antisipasi. Jika menurut Anda tidak aman untuk mengembalikanStreamWriter
dari suatu metode karena dapat otomatis dibuang oleh GC, itu tidak benar.StreamWriter
tidak memiliki finalizer - Saya tidak mengharapkannya, karena alasan ini..NET 4.5 mendapat metode baru untuk itu!
http://msdn.microsoft.com/EN-US/library/gg712853(v=VS.110,d=hv.2).aspx
sumber
bufferSize
adalah1024
. Detailnya ada di sini .Cukup tidak memanggil
Dispose
padaStreamWriter
. Alasan kelas ini dapat dibuang bukan karena memiliki sumber daya yang tidak terkelola tetapi untuk memungkinkan pembuangan aliran yang dengan sendirinya dapat menampung sumber daya yang tidak terkelola. Jika kehidupan aliran yang mendasari ditangani di tempat lain, tidak perlu membuang penulis.sumber
Flush
melakukan pekerjaan jika buffer data?Stream memori memiliki properti ToArray yang dapat digunakan bahkan saat streaming ditutup. To Array menulis konten aliran ke array byte, terlepas dari properti Posisi. Anda dapat membuat aliran baru berdasarkan aliran yang Anda tulis.
sumber
Stream.Position
dapat tidak disebut setelah itu dibuang.Anda perlu membuat turunan StreamWriter dan mengganti metode pembuangannya, dengan selalu meneruskan false ke parameter pembuangan, ini akan memaksa penulis aliran TIDAK untuk menutup, StreamWriter hanya memanggil metode buang dalam metode tutup, jadi tidak perlu menimpanya (tentu saja Anda dapat menambahkan semua konstruktor jika Anda mau, saya hanya punya satu):
sumber
disposing
bendera merupakan bagian dari yangIDisposable
pola . Selalu meneruskanfalse
keDispose(bool)
metode kelas dasar pada dasarnya memberi sinyal ke metodeStreamWriter
yang dipanggil dari finalizer (yang tidak demikian ketika Anda memanggilDispose()
secara eksplisit), dan karenanya tidak boleh mengakses objek yang dikelola. Inilah mengapa ia tidak akan membuang aliran dasar. Namun, cara Anda mencapai ini adalah hack; akan jauh lebih mudah untuk tidak meneleponDispose
dulu!OwnedStream
, yang mengabaikanDispose(bool)
danClose
).