15

我正在调用一个写入流的 dll。dll 中方法的签名如下所示:

public bool SomeMethod(Stream stream);

并且该方法基本上会将二进制数据写入该流。因此,如果我将该方法称为:

var file = System.IO.File.Create("SomeFile.txt");
/* call dll method */ SomeMethod(file); 

然后我将基本上将输出写入该文件。在这个问题中,我将输出写入 networkStream。

无论如何,回到问题上来。我想创建自己的流的原因是因为我想知道某些事件何时发生。例如,如果我在哪里创建自己的流类:

class MyStream : Stream
{
    private long Position;

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

            // implementation goes here

            /* HERE I COULD CALL A CUSTOM EVENT */
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        // SAME THING I WILL LIKE TO PERFORM AN ACTION IF THIS METHOD IS CALLED!
    }

    // etc implement rest of abstract methods....

我正在将该流的输出写入网络,因此如果发生某些事件,我可能想放慢速度。如果我在哪里可以控制 dll,那么我就不会尝试实现这一点。

如果有人可以向我展示如何实现抽象流类的抽象方法的非常基本的示例,我将不胜感激。

4

2 回答 2

23

最简单的自定义流是“包装”其他一些流的流(类似于压缩流)。每个方法都会简单地将其实现重定向到内部流。

class MyStream : Stream
{
 Stream inner;
 public MyStream(Stream inner)
 {
  this.inner = inner;
 }

 public override int Read(byte[] buffer, int offset, int count) 
 { 
    var result = inner.Read(buffer, offset, count);

            /* HERE I COULD CALL A CUSTOM EVENT */ 
   return result;
 } 
///
}

使用示例:functionThatTakesStream(new MyStream(new MemoryStream());.

真正的代码需要在触发事件之前/之后处理内部流操作中的异常,并正确处理 IDisposable。

于 2012-09-08T06:41:26.043 回答
1

如果您只想在调用 Read、Seek 或类似方法时触发事件,请覆盖基类版本,直接调用它们并在之前或之后引发适当的事件。如果您在编写流类方面需要帮助,请查看http://referencesource.microsoft.com/netframework.aspx上提供的 .Net 代码本身。但是,如果您想将流解析为更具可读性的内容,请考虑创建一个IEnumerable<MyClass>读取并处理流的方法。

于 2012-09-08T06:40:23.283 回答