XDocument.Save()
에는 쓸 수있는 Stream
이 필요합니다. StreamContent
은 읽을 수있는 스트림을 기대합니다. 따라서 하나는 다른 하나의 전달자 역할을하는 두 개의 숫자를 사용할 수 있습니다. 나는 그런 종류의 프레임 워크에 존재 생각하지 않는다,하지만 당신은 하나를 직접 작성할 수 있습니다
class ForwardingStream
{
private readonly ReaderStream m_reader;
private readonly WriterStream m_writer;
public ForwardingStream()
{
// bounded, so that writing too much data blocks
var buffers = new BlockingCollection<byte[]>(10);
m_reader = new ReaderStream(buffers);
m_writer = new WriterStream(buffers);
}
private class ReaderStream : Stream
{
private readonly BlockingCollection<byte[]> m_buffers;
private byte[] m_currentBuffer;
private int m_readFromCurrent;
public ReaderStream(BlockingCollection<byte[]> buffers)
{
m_buffers = buffers;
}
public override void Flush()
{}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
if (m_currentBuffer == null)
{
if (!m_buffers.TryTake(out m_currentBuffer, -1))
{
return 0;
}
m_readFromCurrent = 0;
}
int toRead = Math.Min(count, m_currentBuffer.Length - m_readFromCurrent);
Array.Copy(m_currentBuffer, m_readFromCurrent, buffer, offset, toRead);
m_readFromCurrent += toRead;
if (m_readFromCurrent == m_currentBuffer.Length)
m_currentBuffer = null;
return toRead;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
}
private class WriterStream : Stream
{
private readonly BlockingCollection<byte[]> m_buffers;
public WriterStream(BlockingCollection<byte[]> buffers)
{
m_buffers = buffers;
}
public override void Flush()
{}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
if (count == 0)
return;
var copied = new byte[count];
Array.Copy(buffer, offset, copied, 0, count);
m_buffers.Add(copied);
}
public override bool CanRead
{
get { return false; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
protected override void Dispose(bool disposing)
{
m_buffers.CompleteAdding();
base.Dispose(disposing);
}
}
public Stream Reader
{
get { return m_reader; }
}
public Stream Writer
{
get { return m_writer; }
}
}
불행하게도, 당신이 읽고 동일한 스레드에서 동시에 그 스트림에 쓸 수 없습니다. 하지만 Task
을 쓰면 다른 스레드에서 쓸 수 있습니다 :
XDocument doc = …;
var forwardingStream = new ForwardingStream();
var client = new HttpClient();
var content = new StreamContent(forwardingStream.Reader);
Task.Run(() => doc.Save(forwardingStream.Writer));
var response = client.Post(url, content);
Whew! 추가 코드가 많이 있습니다. –
많이 닮았지 만 대부분은 상용구 코드입니다. – svick
@downvoter, 관심있는 댓글? – svick