C# 流管道(流间谍)
C# Stream Pipe (Stream Spy)
我有一个输入流和一个流 reader 组件。这工作正常,但现在我想记录所有流量(在文件中保存一份副本)。
所以我需要监视流。我正在考虑的一个解决方案是流管道(管道)或流包装器,它将流作为输入,然后让我首先了解流量。像这样:
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
}
你要的就是装饰器模式。这是一种动态 adding/modifying 行为的技术:
为此,您需要使用接受另一个 Stream
实例的工厂构造函数来实现抽象 class Stream
。您为抽象 class 的每个 method/overload 提供一个实现,它在修饰的 Stream
上调用相同的 method/overload,并执行您需要的任何额外工作。
完成此操作并用新装饰器装饰 Stream
后,它可以与接受 Stream
的任何其他东西互换使用,包括其他类似的装饰器:装饰器甚至可以是嵌套,就像洋葱层一样组成你需要的行为。
像这样:
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;
}
}
一旦你知道了,你可以这样说:
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);
}
只要有人从流中读取或写入,就会调用您的事件处理程序。
我有一个输入流和一个流 reader 组件。这工作正常,但现在我想记录所有流量(在文件中保存一份副本)。 所以我需要监视流。我正在考虑的一个解决方案是流管道(管道)或流包装器,它将流作为输入,然后让我首先了解流量。像这样:
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
}
你要的就是装饰器模式。这是一种动态 adding/modifying 行为的技术:
为此,您需要使用接受另一个 Stream
实例的工厂构造函数来实现抽象 class Stream
。您为抽象 class 的每个 method/overload 提供一个实现,它在修饰的 Stream
上调用相同的 method/overload,并执行您需要的任何额外工作。
完成此操作并用新装饰器装饰 Stream
后,它可以与接受 Stream
的任何其他东西互换使用,包括其他类似的装饰器:装饰器甚至可以是嵌套,就像洋葱层一样组成你需要的行为。
像这样:
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;
}
}
一旦你知道了,你可以这样说:
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);
}
只要有人从流中读取或写入,就会调用您的事件处理程序。