Объедините два односторонних потока в двусторонний поток - PullRequest
3 голосов
/ 05 декабря 2011

В частности, я использую Ionic.Zlib.ZlibStream для сжатия Zlib на System.Net.Sockets.NetworkStream.

Проблема в том, что ZlibStream - это односторонний поток;Вы можете Read() или Write(), но не оба одновременно.Вам нужно два отдельных потока, один для отправки и один для получения (один сжатие, а другой распаковка).Это прекрасно работает, пока вам не нужно передать его функциям, которые ожидают один двусторонний поток (функциональность Read() и Write()).Например, new System.Net.Security.SslStream(Stream base).

Я понимаю, что могу написать класс Stream, который принимает поток записи и поток чтения и вызывает правильный поток в переопределениях.Но я надеялся, что это уже существует где-то в фреймворке или уже была доступна реализация.

Ответы [ 2 ]

2 голосов
/ 08 декабря 2011

Достаточно просто, если он еще не существует в рамках.

    public class StreamRWJoin : Stream {
        public Stream WriteStream { get; set; }
        public Stream ReadStream { get; set; }
        private bool leaveOpen;

        public StreamRWJoin(Stream readfrom, Stream writeto, bool leaveOpen = false) {
            WriteStream = writeto; ReadStream = readfrom;
            this.leaveOpen = leaveOpen;
        }

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

        public override bool CanSeek {
            get { return false; }
        }

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

        public override void Flush() {
            WriteStream.Flush();
        }

        public override long Length {
            get { throw new NotImplementedException(); }
        }

        public override long Position {
            get {
                throw new NotImplementedException();
            }
            set {
                throw new NotImplementedException();
            }
        }

        public override int Read(byte[] buffer, int offset, int count) {
            return ReadStream.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin) {
            throw new NotImplementedException();
        }

        public override void SetLength(long value) {
            throw new NotImplementedException();
        }

        public override void Write(byte[] buffer, int offset, int count) {
            WriteStream.Write(buffer, offset, count);
        }

        public override void Close() {
            if (!leaveOpen)
                try {
                    WriteStream.Close();
                } finally {
                    ReadStream.Close();
                }
        }

        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
            return ReadStream.BeginRead(buffer, offset, count, callback, state);
        }
        public override int EndRead(IAsyncResult asyncResult) {
            return ReadStream.EndRead(asyncResult);
        }

        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
            return WriteStream.BeginWrite(buffer, offset, count, callback, state);
        }
        public override void EndWrite(IAsyncResult asyncResult) {
            WriteStream.EndWrite(asyncResult);
        }

        public override int ReadByte() {
            return ReadStream.ReadByte();
        }
        public override void WriteByte(byte value) {
            ReadStream.WriteByte(value);
        }

        public override int ReadTimeout {
            get {
                return ReadStream.ReadTimeout;
            }
            set {
                ReadStream.ReadTimeout = value;
            }
        }

        public override int WriteTimeout {
            get {
                return WriteStream.WriteTimeout;
            }
            set {
                WriteStream.WriteTimeout = value;
            }
        }

        public override bool CanTimeout {
            get {
                return ReadStream.CanTimeout || WriteStream.CanTimeout;
            }
        }

        public override int GetHashCode() {
            return ReadStream.GetHashCode() ^ WriteStream.GetHashCode();
        }

        protected override void Dispose(bool disposing) {
            if (disposing && !leaveOpen) {
                try {
                    ReadStream.Dispose();
                } finally {
                    WriteStream.Dispose();
                }
            }
        }

        public override string ToString() {
            return "Read: " + ReadStream.ToString() + ", Write: " + WriteStream.ToString();
        }
    }
2 голосов
/ 05 декабря 2011

Я почти уверен, что нет класса, который сделает это за вас.Однако класс-оболочка, который вам нужно написать, прост и совсем не должен занимать у вас много времени.

Вы, вероятно, унаследуете от Stream , но если вы проанализируете свои потребности идругие доступные типы потоков, вы можете обнаружить, что вам поможет наследование от более специфического класса.

Редактировать : Из-за комментариев Лукаса Б.

Пожалуйста, имейте впомните, что обычное использование Stream объектов требует, чтобы они на самом деле наследовали от Stream .В противном случае вы не можете передать его в качестве параметра большому числу функций, ожидающих поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...