Claire <bl****@blahhhh h.com> wrote:
I'm writing from a serial port into a MemoryStream via a BinaryWriter in my
protocol object.
After I've filled the memorystream, which is approx 200KB in size, I then
pass it up to my datahandler object where I plan to create a BinaryReader to
extract the data and format it ready for a database insert.
At the moment I close the binarywriter earlier than my call to the
datahandler object, and Ive just found out that closing the binarywriter
also closes the memorystream so that it's no longer available.
What's the best/nicest way to do this? Can I attach more than 1
reader/writer to a memorystream at the same time?
I have a nasty solution for you - insert a NonClosingProxy Stream (or
some similarly named class) in between. This class would proxy all the
stream methods *except* Close/Dispose to whatever stream it's
constructed with. Instead of wrapping the MemoryStream directly in a
BinaryWriter, you wrap it in a NonClosingProxy Stream and then wrap the
BinaryWriter round that.
Here's an example of such a class - warning, I haven't tested it
properly as it's part of something else I'm writing but haven't looked
at for a while:
using System;
using System.IO;
using System.Threadin g;
using System.Runtime. Remoting;
namespace MiscUtil.IO
{
/// <summary>
/// Wraps a stream for all operations except Close and Dispose,
/// which merely flush the stream and prevent further operations
/// from being carried out using this wrapper.
/// </summary>
public sealed class NonClosingStrea mWrapper : Stream
{
#region Members specific to this wrapper class
public NonClosingStrea mWrapper(Stream stream)
{
this.stream = stream;
}
Stream stream;
/// <summary>
/// Stream wrapped by this wrapper
/// </summary>
public Stream BaseStream
{
get { return stream; }
}
/// <summary>
/// Whether this stream has been closed or not
/// </summary>
bool closed=false;
/// <summary>
/// Throws an InvalidOperatio nException if the wrapper is
/// closed.
/// </summary>
void CheckClosed()
{
if (closed)
{
throw new InvalidOperatio nException
("Wrapper has been closed or disposed");
}
}
#endregion
#region Overrides of Stream methods and properties
public override IAsyncResult BeginRead
(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
CheckClosed();
return stream.BeginRea d (buffer, offset,
count, callback, state);
}
public override IAsyncResult BeginWrite
(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
CheckClosed();
return stream.BeginWri te
(buffer, offset, count, callback, state);
}
public override bool CanRead
{
get { return closed ? false : stream.CanRead; }
}
public override bool CanSeek
{
get { return closed ? false : stream.CanSeek; }
}
public override bool CanWrite
{
get { return closed ? false : stream.CanWrite ; }
}
/// <summary>
/// This method is not proxied to the underlying stream;
/// instead, the wrapper
/// is marked as unusable for other (non-close/Dispose)
/// operations. The underlying
/// stream is flushed if the wrapper wasn't closed before
/// this call.
/// </summary>
public override void Close()
{
if (!closed)
{
stream.Flush();
}
closed = true;
}
public override ObjRef CreateObjRef(Ty pe requestedType)
{
throw new NotSupportedExc eption();
}
public override int EndRead(IAsyncR esult asyncResult)
{
CheckClosed();
return stream.EndRead (asyncResult);
}
public override void EndWrite(IAsync Result asyncResult)
{
CheckClosed();
stream.EndWrite (asyncResult);
}
public override void Flush()
{
CheckClosed();
stream.Flush();
}
public override object InitializeLifet imeService()
{
throw new NotSupportedExc eption();
}
public override long Length
{
get
{
CheckClosed();
return stream.Length;
}
}
public override long Position
{
get
{
CheckClosed();
return stream.Position ;
}
set
{
CheckClosed();
stream.Position = value;
}
}
public override int Read(byte[] buffer, int offset,
int count)
{
CheckClosed();
return stream.Read(buf fer, offset, count);
}
public override int ReadByte()
{
CheckClosed();
return stream.ReadByte ();
}
public override long Seek(long offset, SeekOrigin origin)
{
CheckClosed();
return stream.Seek(off set, origin);
}
public override void SetLength(long value)
{
CheckClosed();
stream.SetLengt h(value);
}
public override void Write(byte[] buffer, int offset,
int count)
{
CheckClosed();
stream.Write(bu ffer, offset, count);
}
public override void WriteByte(byte value)
{
CheckClosed();
stream.WriteByt e(value);
}
#endregion
}
}
--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too