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

C# 为什么我的非关闭流仍然关闭?,c#,serialization,stream,C#,Serialization,Stream,我有一个非关闭流类,它被包装在带有二进制读取器的using块中,但由于某些原因,当块结束时,我的非关闭流仍然关闭 该流定义为: internal class NonClosingStream : Stream, IDisposable { private Stream baseStream; public NonClosingStream(Stream baseStream) { this.baseStream = baseStream; }

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

该流定义为:

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;
    }
}
读取块如下所示:

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;
    }
}
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);
};
而且它似乎工作得很好,溪流像预期的那样保持开放。所以我想大家的共识是正确的。不知何故,我正在关闭其他地方的河流。当我弄清楚结果后,我会发布结果。谢谢大家

更新

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

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;
    }
}
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);
};
Action assignmentAction=delegate(二进制读取器面包机、对象图形)
{
bReader.ReadByte();//读取下一个操作
bReader.ReadString();//读取字段名
bReader.ReadByte();//读取字段类型
//调用分配lambda
assignmentLambda(读取器,反序列化函数[原语类型],(T)图形);
};
你听到了吗?不显然我也没有。让我们添加一些上下文:

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);
    };

    ...
}
私有静态void反序列化对象(BinaryReader,T图)
{
...
Action assignmentAction=delegate(二进制读取器面包机、对象图形)
{
bReader.ReadByte();//读取下一个操作
bReader.ReadString();//读取字段名
bReader.ReadByte();//读取字段类型
//调用分配lambda
assignmentLambda(读取器,反序列化函数[原语类型],(T)图形);
};
...
}
lambda正在从外部块关闭
读取器
,而不是使用缓存的反序列化程序运行时提供的
bReader
。因此,当反序列化程序运行时,它使用的是已经丢弃的二进制读取器对象,而不是提供给它的新读取器对象。我想问题不是我关闭了流,而是我使用了一个废弃的阅读器。至少这解释了为什么它会工作一次,然后第二次失败,因为第二次它依赖于缓存的反序列化程序。哎呀


谢谢大家。

这取决于非ClosingStream类正在包装的流是否在其他地方引用。如果没有,则底层流将没有引用,因此在之后的某个时刻,它的终结器将关闭流。

因为流不创建内部流,所以外部代码很可能会关闭内部流。您的代码很可能是这样的:

 NonClosingStream nonClosing;
 using(var stream = new FileStream(...))
 {
   nonClosing = new NonClosingStream(stream );
  ....
 } 
 // inner stream now closed and nonClosing will fail all operations.
您的类有两个Dispose()方法。您显式实现的那个。以及从Stream类继承的。问题是,BinaryStream不知道您的bean。它只知道流实现的那个。此外,当您使用BinaryStream(Stream)构造函数时,BinaryStream对象承担传递的流对象的所有权。这意味着它将在自己处理流时处理该流。也许您现在看到了问题所在,将调用继承的Dispose()方法,而不是您的方法。它关闭了基流

这就是流实现Dispose模式的原因。您需要将其改为如下所示:

internal class NonClosingStream : Stream {
    protected override Dispose(bool disposing) {}
}

这里没什么问题。你怎么知道它已经关门了?你怎么知道它在这里是关闭的?因为如果我打开它们,它工作得很好。你怎么知道底层流是关闭的?之后你对它做什么?读取序列化对象后,流上是否有更多数据?展开意味着什么?我看不出与我的问题之间的关系。好吧,你怎么知道这里的流正在关闭?你可能正在关闭其他地方的河流。使用调试器,而不是删除using,以获得更细粒度的结果。如果没有进一步的引用,他将无法观察到流正在关闭。如果流类似于现在可访问的文件,他可以,因为不再有任何进程与之关联。我想这是一个注释,因为它具有高度的推测性。这就是我想要的预期正在发生,但它怎么能为我关闭流?@usr-很可能,不幸的是,注释中的代码不可读:(@sircodesalot?
using
在末尾处理/关闭对象-因此,如果您对流使用
using
,您将传递到
NonClosingStream
,那么内部流将在
using
块的
末尾关闭…但是我的非关闭流将所有流操作传递到
baseStream
,但我要小心永远不要关闭他自己流。这意味着有别的东西在为我关闭它。是的,我一开始是这样做的,但在行为上没有区别。即使它确实以某种方式关闭了我的非关闭流(这真的没有意义),它应该无法关闭此.baseStream
。但目前不能在代码前面关闭,但我明天将重试。