C# Stream Pipe (Stream Spy) [closed]

守給你的承諾、 提交于 2019-12-12 04:56:48

问题


I have an input stream and a stream reader component. This works fine but now I want to log all the traffic (save a copy in a file). So I need to spy on a stream. A solution I am thinking of is a stream pipe (pipeline) or a stream wrapper that takes a stream as input and then gives me a first look at the traffic. Something like this:

    void Init(System.Net.Sockets.NetworkStream stream)
    {
        System.IO.Stream wrappedStream = new MyWrapper(stream);
        wrappedStream.ReadSpy = MyMethod;
        XmlReader reader = XmlReader.Create(wrappedStream);
    }

    // This will get called after some bytes have been read from a stream,
    // but before they get passed to the XmlReader
    byte[] MyMethod(byte[] buffer)
    {
        m_Writer.Write(buffer); // write to a file 
        return buffer; // Give to XmlReader 
    }

回答1:


What you want is called the Decorator Pattern. It's a technique for dynamically adding/modifying behavior:

  • http://sourcemaking.com/design_patterns/decorator
  • http://www.oodesign.com/decorator-pattern.html

To do this, you want to implement the abstract class Stream, with a constructor of factory that accepts another Stream instance. You provide an implementation for every method/overload of the abstract class that invokes the same method/overload on the decorated Stream, plus doing whatever additional work your needs require.

Once you've done that and decorated a Stream with your new decorator, It can be used interchangeably by anything else that accepts a Stream, including other similar decorators: decorators can even be nested, like layers of an onion to compose the behaviors you need.

Something like this:

class StreamInterceptor : Stream
{

  public Stream DecoratedInstance { get; set; }

  public event Action<byte[]> BytesRead;
  public event Action<byte[]> BytesWritten;

  public StreamInterceptor( Stream instance )
  {
    if ( instance == null ) throw new ArgumentNullException("instance");
    this.DecoratedInstance = instance ;
    return ;
  }

  public override bool CanRead
  {
    get { return DecoratedInstance.CanRead; }
  }

  public override bool CanSeek
  {
    get { return DecoratedInstance.CanSeek; }
  }

  public override bool CanWrite
  {
    get { return DecoratedInstance.CanWrite; }
  }

  public override void Flush()
  {
    DecoratedInstance.Flush();
    return;
  }

  public override long Length
  {
    get { return DecoratedInstance.Length; }
  }

  public override long Position
  {
    get { return DecoratedInstance.Position; }
    set { DecoratedInstance.Position = value; }
  }

  public override int Read( byte[] buffer , int offset , int count )
  {
    int bytesRead = DecoratedInstance.Read(buffer, offset, count);

    // raise the bytes read event
    byte[] temp = new byte[bytesRead];
    Array.Copy(buffer,offset,temp,0,bytesRead);
    BytesRead(temp);

    return bytesRead;
  }

  public override long Seek( long offset , SeekOrigin origin )
  {
    return DecoratedInstance.Seek(offset, origin);
  }

  public override void SetLength( long value )
  {
    DecoratedInstance.SetLength(value);
    return;
  }

  public override void Write( byte[] buffer , int offset , int count )
  {

    // raise the bytes written event
    byte[] temp = new byte[count];
    Array.Copy(buffer,offset,temp,0,count);
    BytesWritten(temp);

    DecoratedInstance.Write(buffer, offset, count);
    return;
  }

}

Once you have that, you can say something like this:

static void Main()
{
  StreamInterceptor si = new StreamInterceptor(File.Open("foo.bar.txt",FileMode.Open,FileAccess.ReadWrite,FileShare.Read));

  si.BytesRead    += (bytes) => { Console.WriteLine("{0} bytes read", bytes.Length); } ;
  si.BytesWritten += (bytes) => { Console.WriteLine("{0} bytes written", bytes.Length); } ;

  Stream s = (Stream) si ;
  DoSomethingUseful(s);

}

And your event handler will be invoked whenever somebody reads or writes from the stream.



来源:https://stackoverflow.com/questions/29128485/c-sharp-stream-pipe-stream-spy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!