views:

179

answers:

1

I'm using a library that requires I provide an object that implements this interface:

public interface IConsole {
    TextWriter StandardInput { get; }
    TextReader StandardOutput { get; }
    TextReader StandardError { get; }
}

The object's readers then get used by the library with:

IConsole console = new MyConsole();
int readBytes = console.StandardOutput.Read(buffer, 0, buffer.Length);

Normally the class implementing IConsole has the StandardOutput stream as coming from an external process. In that case the console.StandardOutput.Read calls work by blocking until there is some data written to the StandardOutput stream.

What I'm trying to do is create a test IConsole implementation that uses MemoryStreams and echo's whatever appears on the StandardInput back onto the StandardInput. I tried:

MemoryStream echoOutStream = new MemoryStream();
StandardOutput = new StreamReader(echoOutStream);

But the problem with that is the console.StandardOutput.Read will return 0 rather than block until there is some data. Is there anyway I can get a MemoryStream to block if there is no data available or is there a different in memory stream I could use?

+2  A: 

In the end I found an easy way to do it by inheriting from MemoryStream and taking over the Read and Write methods.

public class EchoStream : MemoryStream {

    private ManualResetEvent m_dataReady = new ManualResetEvent(false);
    private byte[] m_buffer;
    private int m_offset;
    private int m_count;

    public override void Write(byte[] buffer, int offset, int count) {
        m_buffer = buffer;
        m_offset = offset;
        m_count = count;
        m_dataReady.Set();
    }

    public override int Read(byte[] buffer, int offset, int count) {
        if (m_buffer != null) {
            Array.Copy(m_buffer, buffer, m_count);
            m_buffer = null;
            return m_count;
        }
        else {
            // Block until the stream has some more data.
            m_dataReady.Reset();
            m_dataReady.WaitOne();
            Array.Copy(m_buffer, buffer, m_count);
            m_buffer = null;
            return m_count;
        }
    }
}
sipwiz