【问题标题】:C# Stream Pipe (Stream Spy) [closed]C# Stream Pipe (Stream Spy) [关闭]
【发布时间】:2015-05-21 14:48:01
【问题描述】:

我有一个输入流和一个流读取器组件。这工作正常,但现在我想记录所有流量(将副本保存在文件中)。 所以我需要监视流。我正在考虑的一个解决方案是流管道(管道)或流包装器,它将流作为输入,然后让我先看看流量。像这样的:

    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 
    }

【问题讨论】:

  • 您希望从 SO 获得什么类型的帮助?显然,您知道您需要为流提供包装类,并且可能已经尝试编写一个......指定您在这样做时遇到的具体问题将比当前形式的问题更适合 SO(看起来像“请给我codez”,因此可以被视为工具/库的搜索题外)。
  • 不,我还没有尝试自己写,我不喜欢发明自行车。我认为管道将是一个非常有用的抽象,通常这意味着有人已经拥有它而我还没有找到它。
  • 根据您的上述评论,我投票结束:要求我们推荐或查找书籍、工具、软件库、教程或其他非现场资源的问题是Stack Overflow 的题外话 ...相反,请描述问题以及迄今为止为解决该问题所做的工作。"

标签: c# stream pipe splitter


【解决方案1】:

您想要的称为装饰器模式。这是一种动态添加/修改行为的技术:

为此,您需要实现抽象类Stream,并使用一个接受另一个Stream 实例的工厂构造函数。您为抽象类的每个方法/重载提供一个实现,该实现在装饰的Stream 上调用相同的方法/重载,并执行您需要的任何额外工作。

一旦你完成了这个并用你的新装饰器装饰了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);

}

每当有人从流中读取或写入时,都会调用您的事件处理程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多