gpt4 book ai didi

c# - 为什么我的非关闭流仍然关闭?

转载 作者:行者123 更新时间:2023-11-30 17:05:41 30 4
gpt4 key购买 nike

我有一个非关闭流类,它包装在一个带有二进制读取器的 using block 中,但由于某种原因,当该 block 结束时,我的非关闭流仍然关闭。

流定义为:

internal class NonClosingStream : Stream, IDisposable
{
private Stream baseStream;

public NonClosingStream(Stream baseStream)
{
this.baseStream = baseStream;
}

public override bool CanRead{ get { return baseStream.CanRead; } }
public override bool CanSeek{ get { return baseStream.CanSeek; } }
public override bool CanWrite { get { return baseStream.CanWrite; } }

public override void Flush()
{
baseStream.Flush();
}

public override long Length { get { return baseStream.Length; } }

public override long Position
{
get { return baseStream.Position; }
set { baseStream.Position = value; }
}

public override int Read(byte[] buffer, int offset, int count)
{
return baseStream.Read(buffer, offset, count);
}

public override long Seek(long offset, SeekOrigin origin)
{
return baseStream.Seek(offset, origin);
}

public override void SetLength(long value)
{
baseStream.SetLength(value);
}

public override void Write(byte[] buffer, int offset, int count)
{
baseStream.Write(buffer, offset, count);
}

public override void Close()
{
// Disconnects from base stream, but does not close it
this.baseStream = null;
}

void IDisposable.Dispose()
{
// Disconnects from base stream, but does not close it
this.baseStream = null;
}
}

读取 block 看起来像这样:

public T Deserialize<T>(Stream stream)
{
using (NonClosingStream nonClosingStream = new NonClosingStream(stream))
using (BinaryReader reader = new BinaryReader(nonClosingStream, Encoding.ASCII, true))
{
// Read the type name, then convert it to an actual type
String typeName = reader.ReadString();
Type graphType = AvailableTypes.GetType(typeName);

// If a deserializer for this type already exists, use it.
if (deserializerFunctions.ContainsKey(graphType))
{
return (T)deserializerFunctions[graphType](reader);
}

// Otherwise, create one and use it
T graph = (T)FormatterServices.GetUninitializedObject(graphType);

typeof(ServiceSerializer).GetMethod("DeserializeObject",
BindingFlags.NonPublic | BindingFlags.Static)

.MakeGenericMethod(graphType)
.Invoke(this, new Object[] { reader, graph });

return graph;
}
}

我做错了什么?

更新

所以我写了这个小家伙:

static void Main()
{
MemoryStream stream = new MemoryStream();
using (NonClosingStream nonCloser = new NonClosingStream(stream))
using (BinaryWriter writer = new BinaryWriter(nonCloser))
using (BinaryReader reader= new BinaryReader(nonCloser))
{
writer.Write("Lorem ipsum");

stream.Seek(0, SeekOrigin.Begin);
String data = reader.ReadString();

Console.WriteLine(data);
}

stream.Seek(0, SeekOrigin.Begin);

using (NonClosingStream nonCloser = new NonClosingStream(stream))
using (BinaryWriter writer = new BinaryWriter(nonCloser))
using (BinaryReader reader = new BinaryReader(nonCloser))
{
writer.Write("Lorem ipsum");

stream.Seek(0, SeekOrigin.Begin);
String data = reader.ReadString();

Console.WriteLine(data);
}

Console.ReadLine();
}

它似乎工作正常,流像预期的那样保持打开状态。所以我想共识是正确的。我以某种方式关闭了其他地方的流。当我弄清楚我会发布结果时。谢谢大家。

更新

Gaaaahhh,我想通了问题。因此,代码的工作方式是,在序列化/反序列化一个对象的同时,它会从表达式树中构建一个自定义的序列化程序,然后对其进行编译,以便将来的序列化更加流畅。这意味着我的代码中充斥着这样的东西:

Action<BinaryReader, Object> assignmentAction = delegate(BinaryReader bReader, Object oGraph)
{
bReader.ReadByte(); // Read the next action
bReader.ReadString(); // Read the field name
bReader.ReadByte(); // Read the field type

// Call the assignment lambda
assignmentLambda(reader, deserializerFunctions[primitiveType], (T)oGraph);
};

你听懂了吗?不?我显然也没有。让我们添加一些上下文:

private static void DeserializeObject<T>(BinaryReader reader, T graph)
{
...

Action<BinaryReader, Object> assignmentAction = delegate(BinaryReader bReader, Object oGraph)
{
bReader.ReadByte(); // Read the next action
bReader.ReadString(); // Read the field name
bReader.ReadByte(); // Read the field type

// Call the assignment lambda
assignmentLambda(reader, deserializerFunctions[primitiveType], (T)oGraph);
};

...
}

lambda 正在从外部 block 关闭 reader,而不是使用缓存反序列化器运行时提供的 bReader。因此,当反序列化器运行时,它使用的是已经丢弃的二进制读取器对象,而不是提供给它的新对象。我想问题不是我要关闭流,而是我使用的是废弃的阅读器。至少这解释了为什么它会工作一次,然后第二次失败,因为它第二次依赖于缓存的反序列化器。糟糕!

谢谢大家。

最佳答案

由于您的流不会创建内部流,因此很可能外部代码会关闭您的内部流。您的代码很可能如下所示:

 NonClosingStream nonClosing;
using(var stream = new FileStream(...))
{
nonClosing = new NonClosingStream(stream );
....
}
// inner stream now closed and nonClosing will fail all operations.

关于c# - 为什么我的非关闭流仍然关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16202816/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com