我有一個非封閉的流類,封裝在帶有二進制閱讀器的使用塊中,但由於某些原因塊結束時,我的非封閉流仍然關閉。爲什麼我的非關閉流仍然關閉?
流被定義爲:
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;
}
}
我究竟做錯了什麼?
更新
所以我寫了這個小老爹:
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);
};
...
}
拉姆達從外部塊關閉,而不是使用緩存的解串器運行時提供的bReader
超過reader
。因此,當反序列化器運行時,它使用的是已經廢棄的二進制閱讀器對象,而不是提供給它的新對象。我想這個問題不是我關閉了這個流,而是我使用了一個處理過的閱讀器。至少這解釋了爲什麼它會工作一次,然後第二次失敗,因爲第二次它依賴於緩存的解串器。哎呀!
謝謝大家。
在這裏看不到任何問題。你怎麼知道它已關閉?你怎麼知道它已經關閉*在這裏*? – usr 2013-04-24 21:54:32
因爲如果我打開它們,它工作正常。 – sircodesalot 2013-04-24 21:56:12
您如何知道基礎流已關閉?之後你在做什麼?讀取序列化對象後,流中是否有更多數據? – antlersoft 2013-04-24 21:56:47