Last active
November 26, 2015 23:25
-
-
Save benaadams/74eb6be3e2bb5c1c2a64 to your computer and use it in GitHub Desktop.
Stream Evolution in Interfaces (Mixins+Streams)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Interface segregation (Combined Mixin+Non-mixin) | |
// For no-mixins version see https://gist.github.com/benaadams/d35ff5c534a43fd6c89d | |
// For mixins/generic constraints version see https://gist.github.com/benaadams/77c6e7aa34aae92b876a | |
// Do something with sync Reading, Seeking, Disposable stream (Generic Constraints) | |
public static void DoSomething<T>(T stream) where T : IBlockingReader, ISeekable, ISizable, IDisposable | |
{ | |
stream.ReadByte(); | |
stream.SetLength(6); | |
stream.Position = 5; | |
stream.Dispose(); | |
} | |
// Do something with sync Reading, Seeking, Disposable stream (Pre-Mixin) | |
public static void DoSomething(ISeekableDuplexStream stream) | |
{ | |
stream.ReadByte(); | |
stream.SetLength(6); | |
stream.Position = 5; | |
stream.Dispose(); | |
} | |
/// | |
using System.Threading; | |
using System.Threading.Tasks; | |
// Interface segregation | |
namespace System.IO | |
{ | |
/* .NET Framework 1.1 */ | |
public interface IBlockingReader | |
{ | |
int ReadByte(); | |
int Read(byte[] buffer, int offset, int count); | |
} | |
public interface IBlockingWriter | |
{ | |
void Flush(); | |
void WriteByte(byte value); | |
void Write(byte[] buffer, int offset, int count); | |
} | |
public interface ISeekable | |
{ | |
long Position { get; set; } | |
long Length { get; } | |
long Seek(long offset, SeekOrigin origin); | |
} | |
public interface ISizable | |
{ | |
void SetLength(long value); | |
} | |
/* .NET Framework 4.5 */ | |
public interface IReaderAsync | |
{ | |
Task<int> ReadAsync(byte[] buffer, int offset, int count); | |
Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); | |
} | |
public interface IWriterAsync | |
{ | |
Task FlushAsync(); | |
Task FlushAsync(CancellationToken cancellationToken); | |
Task WriteAsync(byte[] buffer, int offset, int count); | |
Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); | |
} | |
// Pre-Mixin | |
namespace Mixin | |
{ | |
/* .NET Framework 1.1 */ | |
public interface IBlockingDuplex : IBlockingReader, IBlockingWriter { } | |
public interface ISeekableReader : IBlockingReader, ISeekable { } | |
public interface ISeekableWriter : IBlockingWriter, ISeekable, ISizable { } | |
public interface ISeekableDuplex : ISeekableReader, ISeekableWriter { } | |
/* .NET Framework 4.5 */ | |
public interface IDuplexAsync : IReaderAsync, IWriterAsync { } | |
namespace Stream | |
{ | |
/* .NET Framework 1.1 */ | |
public interface IBlockingReadStream : IBlockingReader, IDisposable { } | |
public interface IBlockingWriteStream : IBlockingWriter, IDisposable { } | |
public interface IBlockingDuplexStream : IBlockingReadStream, IBlockingWriteStream { } | |
public interface ISeekableStream : ISeekable, IDisposable { } | |
public interface ISeekableReadStream : IBlockingReadStream, ISeekableStream, ISeekableReader { } | |
public interface ISeekableWriteStream : IBlockingWriteStream, ISeekableStream, ISeekableWriter { } | |
public interface ISeekableDuplexStream : ISeekableReadStream, ISeekableWriteStream, IBlockingDuplexStream, ISeekableDuplex { } | |
/* .NET Framework 4.5 */ | |
public interface IReadStreamAsync : IReaderAsync, IDisposable { } | |
public interface IWriteStreamAsync : IWriterAsync, IDisposable { } | |
public interface IDuplexStreamAsync : IReadStreamAsync, IWriteStreamAsync, IDuplexAsync { } | |
} | |
} | |
namespace Extensions | |
{ | |
public static partial class ReaderWriterExtensions | |
{ | |
/* .NET Framework 4.0 */ | |
private const int _DefaultCopyBufferSize = 81920; | |
public static void CopyTo(this IBlockingReader source, IBlockingWriter destination) | |
{ | |
source.CopyTo(destination, _DefaultCopyBufferSize); | |
} | |
public static void CopyTo(this IBlockingReader source, IBlockingWriter destination, int bufferSize) | |
{ | |
byte[] buffer = new byte[bufferSize]; | |
int read; | |
while ((read = source.Read(buffer, 0, buffer.Length)) != 0) | |
destination.Write(buffer, 0, read); | |
} | |
/* .NET Framework 4.5 */ | |
public static Task CopyToAsync(this IReaderAsync source, IWriterAsync destination) | |
{ | |
return source.CopyToAsync(destination, _DefaultCopyBufferSize, CancellationToken.None); | |
} | |
public static Task CopyToAsync(this IReaderAsync source, IWriterAsync destination, int bufferSize) | |
{ | |
return source.CopyToAsync(destination, bufferSize, CancellationToken.None); | |
} | |
public static async Task CopyToAsync(this IReaderAsync source, IWriterAsync destination, int bufferSize, CancellationToken cancellationToken) | |
{ | |
byte[] buffer = new byte[bufferSize]; | |
int bytesRead; | |
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) | |
{ | |
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); | |
} | |
} | |
} | |
namespace Implementer | |
{ | |
public static partial class ReaderWriterImplementerExtensions | |
{ | |
/* .NET Framework 1.1 */ | |
public static int ReadByteInner(this IBlockingReader source) | |
{ | |
byte[] oneByteArray = new byte[1]; | |
int r = source.Read(oneByteArray, 0, 1); | |
if (r == 0) | |
return -1; | |
return oneByteArray[0]; | |
} | |
public static void WriteByteInner(this IBlockingWriter destination, byte value) | |
{ | |
byte[] oneByteArray = new byte[1]; | |
oneByteArray[0] = value; | |
destination.Write(oneByteArray, 0, 1); | |
} | |
} | |
} | |
} | |
} | |
#if !FEATURE_CORECLR | |
namespace System.IO | |
{ | |
/* .NET Framework 1.1 */ | |
public interface IStream | |
{ | |
void Close(); | |
} | |
public interface IAsyncReader | |
{ | |
IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state); | |
int EndRead(IAsyncResult asyncResult); | |
} | |
public interface IAsyncWriter | |
{ | |
IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state); | |
void EndWrite(IAsyncResult asyncResult); | |
} | |
/* .NET Framework 2.0 */ | |
public interface IReadTimeout | |
{ | |
int ReadTimeout { get; set; } | |
} | |
public interface IWriteTimeout | |
{ | |
int WriteTimeout { get; set; } | |
} | |
// Pre-Mixin | |
namespace Mixin | |
{ | |
/* .NET Framework 2.0 */ | |
public interface IAsyncTimeoutReader : IAsyncReader, IReadTimeout { } | |
public interface IAsyncTimeoutWriter : IAsyncWriter, IWriteTimeout { } | |
/* .NET Framework 1.1 */ | |
public interface IAsyncReadStream : IAsyncReader, IStream { } | |
public interface IAsyncWriteStream : IAsyncWriter, IStream { } | |
public interface IAsyncDuplexStream : IAsyncReadStream, IAsyncWriteStream { } | |
namespace Stream | |
{ | |
/* .NET Framework 2.0 */ | |
public interface IAsyncTimeoutReadStream : IAsyncReadStream, IAsyncTimeoutReader { } | |
public interface IAsyncTimeoutWriteStream : IAsyncWriteStream, IAsyncTimeoutWriter { } | |
public interface IAsyncTimeoutDuplexStream : IAsyncTimeoutReadStream, IAsyncTimeoutWriteStream { } | |
} | |
} | |
namespace Extensions | |
{ | |
public static partial class StreamExtensions | |
{ | |
/* .NET Framework 4.5 */ | |
public static Task<int> ReadAsync(this IAsyncReader source, byte[] buffer, int offset, int count) | |
{ | |
return Task<int>.Factory.FromAsync(source.BeginRead, source.EndRead, buffer, offset, count, null); | |
} | |
public static Task<int> ReadAsync(this IAsyncReader source, byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |
{ | |
return cancellationToken.IsCancellationRequested | |
? Task.FromCanceled<int>(cancellationToken) | |
: Task<int>.Factory.FromAsync(source.BeginRead, source.EndRead, buffer, offset, count, null); | |
} | |
public static Task WriteAsync(this IAsyncWriter destination, byte[] buffer, int offset, int count) | |
{ | |
return Task.Factory.FromAsync(destination.BeginWrite, destination.EndWrite, buffer, offset, count, null); | |
} | |
public static Task WriteAsync(this IAsyncWriter destination, byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |
{ | |
return cancellationToken.IsCancellationRequested | |
? Task.FromCanceled<int>(cancellationToken) | |
: Task.Factory.FromAsync(destination.BeginWrite, destination.EndWrite, buffer, offset, count, null); | |
} | |
} | |
namespace Conversion | |
{ | |
public static partial class StreamLegacyConverterExtensions | |
{ | |
public static IAsyncReader AsAsyncReader(this IReaderAsync stream) => null; | |
// Use timed CTS | |
public static IAsyncTimeoutReader AsAsyncTimeoutReader(this IReaderAsync stream) => null; | |
// ... | |
} | |
} | |
} | |
} | |
#endif // !FEATURE_CORECLR | |
/* | |
#if FEATURE_REMOTING | |
public class Stream : MarshalByRefObject, ISeekableDuplexStream, IAsyncTimeoutDuplexStream, IDuplexStreamAsync | |
#endif | |
#if !FEATURE_REMOTING && !FEATURE_CORECLR | |
public class Stream : ISeekableDuplexStream, IAsyncTimeoutDuplexStream, IDuplexStreamAsync | |
#endif | |
#if FEATURE_CORECLR | |
public class Stream : ISeekableDuplexStream, IDuplexStreamAsync | |
#endif | |
{ | |
public static readonly Stream Null = new NullStream(); | |
public static Stream Synchronized(Stream stream) | |
{ | |
} | |
// ... | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment