diff --git a/CatLib.Core.sln b/CatLib.Core.sln
index 22d9a7b..1f1cacb 100644
--- a/CatLib.Core.sln
+++ b/CatLib.Core.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2036
+VisualStudioVersion = 15.0.26430.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CatLib.Core", "src\CatLib.Core\CatLib.Core.csproj", "{4204658E-81FD-4106-A347-890CD369C8A4}"
EndProject
diff --git a/README.md b/README.md
index 8898278..37fe7c6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-

+
@@ -28,7 +28,7 @@
**使用Nuget安装**
```PM
-Install-Package CatLib.Core -Version 1.2.9
+Install-Package CatLib.Core -Version 1.2.10
```
**直接下载发布版本**
diff --git a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj
index 606b700..b26650e 100644
--- a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj
+++ b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj
@@ -106,6 +106,7 @@
+
diff --git a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj
index 3fb9c76..f52904b 100644
--- a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj
+++ b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj
@@ -52,6 +52,7 @@
+
diff --git a/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs b/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs
index 3a549a0..3ac60bf 100644
--- a/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs
+++ b/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs
@@ -25,5 +25,5 @@
[assembly: Guid("3c9f4024-910c-4881-a04d-34a6c3a09019")]
-[assembly: AssemblyVersion("1.2.9.0")]
-[assembly: AssemblyFileVersion("1.2.9.0")]
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.10.0")]
diff --git a/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs b/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs
index 519f57e..cba9cbe 100644
--- a/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs
+++ b/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs
@@ -742,7 +742,7 @@ public void TestOverflowParamNum()
{
container.Call(cls, "GetNumber", new object[256]);
}
- catch (Exception ex)
+ catch (Exception)
{
isThrow = true;
}
diff --git a/src/CatLib.Core.Tests/Support/Stream/PipelineStreamTests.cs b/src/CatLib.Core.Tests/Support/Stream/PipelineStreamTests.cs
new file mode 100644
index 0000000..151d72e
--- /dev/null
+++ b/src/CatLib.Core.Tests/Support/Stream/PipelineStreamTests.cs
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the CatLib package.
+ *
+ * (c) Yu Bin
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * Document: http://catlib.io/
+ */
+
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace CatLib.Core.Tests.Support.Stream
+{
+ [TestClass]
+ public class PipelineStreamTests
+ {
+ private PipelineStream stream;
+
+ [TestMethod]
+ public void TestPipeline()
+ {
+ stream = new PipelineStream(256);
+ ThreadPool.QueueUserWorkItem(WriteThread);
+
+ var wrote = false;
+ stream.OnWrote += (_) =>
+ {
+ wrote = true;
+ };
+ var data = new byte[100];
+ int read;
+ var actual = new StringBuilder();
+ var rand = new Random();
+ while ((read = stream.Read(data, 0, data.Length)) != 0)
+ {
+ var str = Encoding.UTF8.GetString(data, 0, read);
+ actual.Append(str);
+ Thread.Sleep(rand.Next(1, 5));
+ }
+ stream.Dispose();
+
+ var expected = new StringBuilder();
+ for (var i = 0; i < 1000; i++)
+ {
+ expected.Append("0123456789");
+ }
+
+ Assert.AreEqual(expected.ToString(), actual.ToString());
+ Assert.AreEqual(true, wrote);
+ }
+
+ public void WriteThread(object obj)
+ {
+ var data = Encoding.UTF8.GetBytes("0123456789");
+ for (var i = 0; i < 1000; i++)
+ {
+ stream.Write(data, 0, data.Length);
+ }
+ stream.Close();
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(ObjectDisposedException))]
+ public void TestClosedAndWrite()
+ {
+ var stream = new PipelineStream(256);
+ Assert.AreEqual(true, stream.CanWrite);
+ stream.Write(Encoding.UTF8.GetBytes("0123456789"), 0, 10);
+ stream.Close();
+ Assert.AreEqual(false, stream.CanWrite);
+ Assert.AreEqual(true, stream.CanRead);
+ Assert.AreEqual(true, stream.Closed);
+ stream.Write(Encoding.UTF8.GetBytes("0123456789"), 0, 10);
+ }
+
+
+ [TestMethod]
+ [ExpectedException(typeof(ObjectDisposedException))]
+ public void TestDisposeAndWrite()
+ {
+ var stream = new PipelineStream(256);
+ Assert.AreEqual(true, stream.CanWrite);
+ Assert.AreEqual(false, stream.CanRead);
+ stream.Dispose();
+ Assert.AreEqual(false, stream.CanWrite);
+ Assert.AreEqual(false, stream.CanRead);
+ stream.Write(Encoding.UTF8.GetBytes("0123456789"), 0, 10);
+ }
+
+ [TestMethod]
+ public void TestCanReadCanWrite()
+ {
+ var stream = new PipelineStream(256);
+ stream.Write(Encoding.UTF8.GetBytes("0123456789"), 0, 10);
+ Assert.AreEqual(true, stream.CanWrite);
+ Assert.AreEqual(true, stream.CanRead);
+ }
+
+ [TestMethod]
+ public void TestCanSeek()
+ {
+ var stream = new PipelineStream(256);
+ Assert.AreEqual(false, stream.CanSeek);
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void TestSeek()
+ {
+ var stream = new PipelineStream(256);
+ stream.Seek(0, SeekOrigin.Begin);
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void TestSetLength()
+ {
+ var stream = new PipelineStream(256);
+ stream.SetLength(0);
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void TestSetPosition()
+ {
+ var stream = new PipelineStream(256);
+ stream.Position = 10;
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void TestGetPosition()
+ {
+ var stream = new PipelineStream(256);
+ var pos = stream.Position;
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void TestGetLength()
+ {
+ var stream = new PipelineStream(256);
+ var length = stream.Length;
+ }
+ }
+}
diff --git a/src/CatLib.Core.Tests/Support/Template/ManagerTests.cs b/src/CatLib.Core.Tests/Support/Template/ManagerTests.cs
index 23df793..644cc1f 100644
--- a/src/CatLib.Core.Tests/Support/Template/ManagerTests.cs
+++ b/src/CatLib.Core.Tests/Support/Template/ManagerTests.cs
@@ -51,7 +51,7 @@ public void TestReleaseExtendAndMake()
return tmp = new TestManagerClass();
});
- cls.ReleaseExtend();
+ cls.RemoveExtend();
ExceptionAssert.Throws(() =>
{
diff --git a/src/CatLib.Core.Tests/Support/Template/SingleManagerTests.cs b/src/CatLib.Core.Tests/Support/Template/SingleManagerTests.cs
index 5affb4f..a8760a0 100644
--- a/src/CatLib.Core.Tests/Support/Template/SingleManagerTests.cs
+++ b/src/CatLib.Core.Tests/Support/Template/SingleManagerTests.cs
@@ -129,7 +129,7 @@ public void TestReleaseExtend()
manager.Extend(() => new InterfaceImpl(), "hello");
Assert.AreEqual(true, manager.ContainsExtend("hello"));
- manager.ReleaseExtend("hello");
+ manager.RemoveExtend("hello");
Assert.AreEqual(false, manager.ContainsExtend());
Assert.AreEqual(false, manager.ContainsExtend("hello"));
}
diff --git a/src/CatLib.Core.Tests/Support/Util/ArrTests.cs b/src/CatLib.Core.Tests/Support/Util/ArrTests.cs
index e719e6a..a87d5a1 100644
--- a/src/CatLib.Core.Tests/Support/Util/ArrTests.cs
+++ b/src/CatLib.Core.Tests/Support/Util/ArrTests.cs
@@ -33,6 +33,36 @@ public void TestMerge()
Assert.AreEqual(3, newArr.Length);
}
+ [TestMethod]
+ public void TestMergeNull()
+ {
+ var arr1 = new[] { "1", "2" };
+ string[] arr2 = null;
+ var arr3 = new[] { "3" };
+ var newArr = Arr.Merge(arr1, arr2, arr3);
+ Assert.AreEqual(3, newArr.Length);
+ var i = 0;
+ foreach (var result in newArr)
+ {
+ Assert.AreEqual((++i).ToString(), result);
+ }
+ }
+
+ [TestMethod]
+ public void TestMergeEmpty()
+ {
+ var arr1 = new[] { "1", "2" };
+ var arr2 = new string[0];
+ var arr3 = new[] { "3" };
+ var newArr = Arr.Merge(arr1, arr2, arr3);
+ Assert.AreEqual(3, newArr.Length);
+ var i = 0;
+ foreach (var result in newArr)
+ {
+ Assert.AreEqual((++i).ToString(), result);
+ }
+ }
+
[TestMethod]
public void TestRandom()
{
diff --git a/src/CatLib.Core.Tests/Support/Util/StreamExtensionTests.cs b/src/CatLib.Core.Tests/Support/Util/StreamExtensionTests.cs
index ed5ea25..5d2ad7e 100644
--- a/src/CatLib.Core.Tests/Support/Util/StreamExtensionTests.cs
+++ b/src/CatLib.Core.Tests/Support/Util/StreamExtensionTests.cs
@@ -28,5 +28,52 @@ public void TestAppendTo()
Assert.AreEqual(11, count);
Assert.AreEqual("Hello world", Encoding.Default.GetString(stream2.GetBuffer(), 0, (int)stream2.Length));
}
+
+ [TestMethod]
+ public void TestStreamToText()
+ {
+ var stream1 = new MemoryStream(Encoding.Default.GetBytes("Hello world"));
+ Assert.AreEqual("Hello world", stream1.ToText());
+ }
+
+ [TestMethod]
+ public void TestStreamToTextOtherStream()
+ {
+ var stream1 = new StorageStream(new MemoryStorage());
+ stream1.Write(Encoding.Default.GetBytes("Hello world"), 0, 11);
+ stream1.Seek(0, SeekOrigin.Begin);
+ Assert.AreEqual("Hello world", stream1.ToText());
+ }
+
+ [TestMethod]
+ public void TestStreamToTextLarage()
+ {
+ var stream1 = new StorageStream(new MemoryStorage());
+ var builder = new StringBuilder();
+ for (var i = 0; i < (ThreadStatic.Buffer.Length / 10) + 1; i++)
+ {
+ stream1.Write(Encoding.Default.GetBytes("1234567890"), 0, 10);
+ builder.Append("1234567890");
+ }
+ stream1.Seek(0, SeekOrigin.Begin);
+ Assert.AreEqual(builder.ToString(), stream1.ToText());
+ }
+
+ [TestMethod]
+ public void TestStreamToTextEmpty()
+ {
+ var stream1 = new MemoryStream(0);
+ Assert.AreEqual(string.Empty, stream1.ToText());
+ }
+
+ [TestMethod]
+ public void TestStreamClosed()
+ {
+ var stream1 = new MemoryStream(0);
+ Assert.AreEqual(string.Empty, stream1.ToText(null, false));
+ Assert.AreEqual(true, stream1.CanWrite);
+ Assert.AreEqual(string.Empty, stream1.ToText());
+ Assert.AreEqual(false, stream1.CanWrite);
+ }
}
}
diff --git a/src/CatLib.Core/CatLib.Core.csproj b/src/CatLib.Core/CatLib.Core.csproj
index fd50440..997e88a 100644
--- a/src/CatLib.Core/CatLib.Core.csproj
+++ b/src/CatLib.Core/CatLib.Core.csproj
@@ -86,6 +86,7 @@
+
diff --git a/src/CatLib.Core/CatLib/Application.cs b/src/CatLib.Core/CatLib/Application.cs
index 62fd368..b9a8666 100644
--- a/src/CatLib.Core/CatLib/Application.cs
+++ b/src/CatLib.Core/CatLib/Application.cs
@@ -23,7 +23,7 @@ public class Application : Container, IApplication, IOriginalDispatcher
///
/// 版本号
///
- private readonly Version version = new Version("1.2.9");
+ private readonly Version version = new Version("1.2.10");
///
/// 框架启动流程
diff --git a/src/CatLib.Core/Properties/AssemblyInfo.cs b/src/CatLib.Core/Properties/AssemblyInfo.cs
index 7121d22..2444b09 100644
--- a/src/CatLib.Core/Properties/AssemblyInfo.cs
+++ b/src/CatLib.Core/Properties/AssemblyInfo.cs
@@ -26,8 +26,8 @@
[assembly: Guid("4204658e-81fd-4106-a347-890cd369c8a4")]
-[assembly: AssemblyVersion("1.2.9.0")]
-[assembly: AssemblyFileVersion("1.2.9.0")]
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.10.0")]
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor"),
InternalsVisibleTo("Assembly-CSharp-Editor-firstpass"),
diff --git a/src/CatLib.Core/Support/Stream/PipelineStream.cs b/src/CatLib.Core/Support/Stream/PipelineStream.cs
new file mode 100644
index 0000000..6f1a461
--- /dev/null
+++ b/src/CatLib.Core/Support/Stream/PipelineStream.cs
@@ -0,0 +1,325 @@
+/*
+ * This file is part of the CatLib package.
+ *
+ * (c) Yu Bin
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * Document: http://catlib.io/
+ */
+
+using System;
+using System.IO;
+using System.Threading;
+
+namespace CatLib
+{
+ ///
+ /// 管道通讯流
+ /// 一读一写线程安全
+ ///
+ public class PipelineStream : Stream
+ {
+ ///
+ /// 可以被读取的长度
+ ///
+ private volatile int count;
+
+ ///
+ /// 容量
+ ///
+ private readonly int capacity;
+
+ ///
+ /// 休眠时间
+ ///
+ private readonly int sleep;
+
+ ///
+ /// 环形缓冲区
+ ///
+ private readonly RingBuffer ringBuffer;
+
+ ///
+ /// 当写入完成后触发
+ ///
+ public event Action OnWrote;
+
+ ///
+ /// 是否已经被释放了
+ ///
+ private volatile bool disabled;
+
+ ///
+ /// 是否已经关闭流了
+ ///
+ private volatile bool closed;
+
+ ///
+ /// 总流量
+ ///
+ public long TotalFlow { get; private set; }
+
+ ///
+ /// 是否可以被读取
+ ///
+ public override bool CanRead
+ {
+ get { return count > 0 && !disabled; }
+ }
+
+ ///
+ /// 是否可以被写入
+ ///
+ public override bool CanWrite
+ {
+ get { return count < capacity && !closed; }
+ }
+
+ ///
+ /// 偏移位置(不支持)
+ ///
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ ///
+ /// 流的长度
+ ///
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ ///
+ /// 是否能够设定偏移量
+ ///
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ ///
+ /// 是否已经关闭了流
+ ///
+ public bool Closed
+ {
+ get { return closed; }
+ }
+
+ ///
+ /// 管道通讯流
+ ///
+ /// 缓冲区容量
+ /// 线程休眠时间
+ public PipelineStream(int capacity = 4096, int sleep = 1)
+ {
+ this.capacity = capacity.ToPrime();
+ this.sleep = Math.Max(0, sleep);
+ TotalFlow = 0;
+ ringBuffer = new RingBuffer(this.capacity, false);
+ }
+
+ ///
+ /// GC回收时
+ ///
+ ~PipelineStream()
+ {
+ Dispose(!disabled);
+ }
+
+ ///
+ /// 偏移位置(不支持)
+ ///
+ /// 偏移量
+ /// 偏移方向
+ ///
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// 设定流的长度(不支持)
+ ///
+ /// 长度
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// 刷新缓冲区
+ ///
+ public override void Flush()
+ {
+ // ignore
+ }
+
+ ///
+ /// 将流中的数据读取到指定缓冲区
+ ///
+ /// 指定缓冲区
+ /// 缓冲区起始偏移量
+ /// 读取的长度
+ /// 实际读取的长度
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ while (true)
+ {
+ while (this.count <= 0)
+ {
+ AssertDisabled();
+ if (closed)
+ {
+ return 0;
+ }
+ Thread.Sleep(sleep);
+ }
+
+ AssertDisabled();
+
+ lock (ringBuffer.SyncRoot)
+ {
+ AssertDisabled();
+ if (this.count <= 0)
+ {
+ if (closed)
+ {
+ return 0;
+ }
+ continue;
+ }
+
+ try
+ {
+ var read = ringBuffer.Read(buffer, offset, count);
+ this.count -= read;
+ TotalFlow += read;
+ return read;
+ }
+ finally
+ {
+ Guard.Requires(this.count >= 0);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 将指定缓冲区数据写入流中
+ ///
+ /// 指定缓冲区
+ /// 缓冲区起始偏移量
+ /// 写入的长度
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ while (true)
+ {
+ while ((capacity - this.count) < count)
+ {
+ AssertDisabled();
+ AssertClosed();
+
+ Thread.Sleep(sleep);
+ }
+
+ AssertDisabled();
+ AssertClosed();
+
+ lock (ringBuffer.SyncRoot)
+ {
+ AssertDisabled();
+ AssertClosed();
+
+ if ((capacity - this.count) < count)
+ {
+ continue;
+ }
+
+ Guard.Requires(ringBuffer.Write(buffer, offset, count) == count);
+ this.count += count;
+
+ if (OnWrote != null)
+ {
+ OnWrote(this);
+ }
+
+ return;
+ }
+ }
+ }
+
+ ///
+ /// 关闭流
+ ///
+ public override void Close()
+ {
+ if (closed)
+ {
+ return;
+ }
+
+ lock (ringBuffer.SyncRoot)
+ {
+ closed = true;
+ }
+ }
+
+ ///
+ /// 断言关闭
+ ///
+ protected void AssertClosed()
+ {
+ if (closed)
+ {
+ throw new ObjectDisposedException("PipelineStream", "Stream is Closed Cannot write");
+ }
+ }
+
+ ///
+ /// 断言释放
+ ///
+ protected void AssertDisabled()
+ {
+ if (disabled)
+ {
+ throw new ObjectDisposedException("PipelineStream", "Stream is dispose");
+ }
+ }
+
+ ///
+ /// 释放资源
+ ///
+ /// 是否进行释放
+ protected override void Dispose(bool disposing)
+ {
+ if (!disposing || disabled)
+ {
+ return;
+ }
+
+ lock (ringBuffer.SyncRoot)
+ {
+ if (disabled)
+ {
+ return;
+ }
+
+ try
+ {
+ disabled = true;
+ closed = true;
+ ringBuffer.Dispose();
+ }
+ finally
+ {
+ base.Dispose(true);
+ }
+ }
+ }
+ }
+}
diff --git a/src/CatLib.Core/Support/Util/Arr.cs b/src/CatLib.Core/Support/Util/Arr.cs
index 879834b..8e2e189 100644
--- a/src/CatLib.Core/Support/Util/Arr.cs
+++ b/src/CatLib.Core/Support/Util/Arr.cs
@@ -31,13 +31,26 @@ public static T[] Merge(params T[][] sources)
var length = 0;
foreach (var source in sources)
{
+ if (source == null || source.Length <= 0)
+ {
+ continue;
+ }
length += source.Length;
}
+ if (length <= 0)
+ {
+ return new T[0];
+ }
+
var merge = new T[length];
var current = 0;
foreach (var source in sources)
{
+ if (source == null || source.Length <= 0)
+ {
+ continue;
+ }
Array.Copy(source, 0, merge, current, source.Length);
current += source.Length;
}
diff --git a/src/CatLib.Core/Support/Util/Extension/StreamExtension.cs b/src/CatLib.Core/Support/Util/Extension/StreamExtension.cs
index 261fb84..e263269 100644
--- a/src/CatLib.Core/Support/Util/Extension/StreamExtension.cs
+++ b/src/CatLib.Core/Support/Util/Extension/StreamExtension.cs
@@ -11,6 +11,7 @@
using System;
using System.IO;
+using System.Text;
namespace CatLib
{
@@ -19,6 +20,14 @@ namespace CatLib
///
public static class StreamExtension
{
+ ///
+ /// 编码
+ ///
+ private static Encoding Encoding
+ {
+ get { return Encoding.UTF8; }
+ }
+
///
/// 将当前流追加到目标流中
///
@@ -44,7 +53,7 @@ public static long AppendTo(this Stream source, Stream destination, byte[] buffe
long result = 0;
int read;
- while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
+ while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, read);
result += read;
@@ -52,5 +61,68 @@ public static long AppendTo(this Stream source, Stream destination, byte[] buffe
return result;
}
+
+ ///
+ /// 将流转为字符串
+ ///
+ /// 源数据流
+ /// 编码
+ /// 是否自动关闭流
+ /// 字符串
+ public static string ToText(this Stream source, Encoding encoding = null, bool closed = true)
+ {
+ try
+ {
+ encoding = encoding ?? Encoding;
+ if (source is MemoryStream)
+ {
+ var memoryStream = (MemoryStream) source;
+ byte[] buffer;
+ try
+ {
+ buffer = memoryStream.GetBuffer();
+ }
+ catch (UnauthorizedAccessException)
+ {
+ buffer = memoryStream.ToArray();
+ }
+
+ return encoding.GetString(buffer, 0, (int) memoryStream.Length);
+ }
+
+ var length = 0;
+ try
+ {
+ length = (int) source.Length;
+ }
+ catch (NotSupportedException)
+ {
+ // ignore
+ }
+
+ MemoryStream targetStream;
+ if (length > 0 && length <= ThreadStatic.Buffer.Length)
+ {
+ targetStream = new MemoryStream(ThreadStatic.Buffer, 0, ThreadStatic.Buffer.Length, true, true);
+ }
+ else
+ {
+ targetStream = new MemoryStream(length);
+ }
+
+ using (targetStream)
+ {
+ var read = source.AppendTo(targetStream);
+ return encoding.GetString(targetStream.GetBuffer(), 0, (int) read);
+ }
+ }
+ finally
+ {
+ if (closed)
+ {
+ source.Dispose();
+ }
+ }
+ }
}
}