SslStream
当使用该方法正常读取时Read(byte[] buffer, int offset, int count)
,我得到了预期的结果。
但是,如果我将SslStream
对象移动到 newAppDomain
中,读取似乎仍然正常运行(即返回正确的读取字节数),但buffer
数组为空。
为什么是这样?
SslStream
当使用该方法正常读取时Read(byte[] buffer, int offset, int count)
,我得到了预期的结果。
但是,如果我将SslStream
对象移动到 newAppDomain
中,读取似乎仍然正常运行(即返回正确的读取字节数),但buffer
数组为空。
为什么是这样?
经过一番调查,参数数组的内容似乎没有跨 AppDomains 编组(可能是出于性能原因)。
因此,buffer
参数中的数据只传递一种方式。本地 AppDomain 中的调用者将看不到对远程 AppDomain 中数组的修改。
强制返回数组参数中的数据的方法是给参数加上[Out]
属性。
要解决问题中所述的问题,请为SslStream
和使用它创建一个包装类:
[Serializable]
internal class SslStreamWrapper : SslStream
{
public SslStreamWrapper(
Stream innerStream,
Boolean leaveInnerStreamOpen,
RemoteCertificateValidationCallback validationCallback,
LocalCertificateSelectionCallback selectionCallback)
: base(innerStream, leaveInnerStreamOpen, validationCallback, selectionCallback)
{
}
// Add the [Out] attribute to the 'buffer' parameter.
public override Int32 Read([In, Out] Byte[] buffer, Int32 offset, Int32 count)
{
return base.Read(buffer, offset, count);
}
}
该类具有[Serializable]
属性,允许它在 AppDomain 之间传递,并且包含隐式[In]
参数是为了与其他 Stream 类保持一致。
许多其他 .NET 类继承自Stream
(例如MemoryStream
和BufferedStream
- 甚至Stream
其自身)在方法中包含参数的[In, Out]
属性。buffer
Read()
我想知道是否故意选择省略它们SslStream
... 这适用于所有版本的 .NET。
这是@JonSkeet 在对已接受答案的评论中建议的使用组合而不是继承的替代解决方案的代码:
[Serializable]
public class CrossAppDomainStreamWrapper : Stream
{
public CrossAppDomainStreamWrapper(Stream stream) => Stream = stream;
public Stream Stream { get; }
public override bool CanRead => Stream.CanRead;
public override bool CanSeek => Stream.CanSeek;
public override bool CanWrite => Stream.CanWrite;
public override long Length => Stream.Length;
public override long Position
{
get => Stream.Position;
set => Stream.Position = value;
}
public override void Flush() =>
Stream.Flush();
public override long Seek(long offset, SeekOrigin origin) =>
Stream.Seek(offset, origin);
public override void SetLength(long value) =>
Stream.SetLength(value);
public override int Read([In, Out] byte[] buffer, int offset, int count) =>
Stream.Read(buffer, offset, count);
public override void Write(byte[] buffer, int offset, int count) =>
Stream.Write(buffer, offset, count);
}