public Stream GetStream()
        {
            _mutex.Wait();

            // Make sure we have a seekable stream
            Stream contentStream = _stream;

            if (!contentStream.CanSeek)
            {
                // If the stream can't seek, wrap it in a buffered stream that can
                MemoryStream bufferStream = _memoryStreamFactory.GetStream();
                contentStream = new SeekableStream(_stream, bufferStream);
            }

            contentStream.Position = 0;

            // Even if we don't need to synchronize, return a wrapping stream to ensure the underlying
            // stream isn't disposed after every use
            return(new SynchronizedStream(contentStream, _mutex));
        }
 /// <summary>
 /// Retrieve a new <see cref="MemoryStream"/> object with contents copied from the provided
 /// buffer. The provided buffer is not wrapped or used after construction.
 /// </summary>
 /// <remarks>The new stream's position is set to the beginning of the stream when returned.</remarks>
 /// <param name="factory">The memory stream factory.</param>
 /// <param name="buffer">The byte buffer to copy data from.</param>
 /// <returns>A <see cref="MemoryStream"/>.</returns>
 public static MemoryStream GetStream(this IMemoryStreamFactory factory, byte[] buffer) => factory.GetStream(buffer, 0, buffer.Length);