简而言之,你正在走你不能走的捷径。正如您的问题标题已经字面上所说的那样,您正在尝试使用一个依赖于您处置的对象的对象。
您要做的是打开一个文件,从中读取有关其内部的一些信息(不是实际的内部本身),然后关闭该文件,然后尝试使用该信息实际从该文件中读取。不可能; 该文件已经关闭。就像你不能从它自己的using
块内返回一个一次性对象而不最终得到一个已处置且因此不可用的对象一样,你显然也不能返回依赖于一次性对象的东西。
getMyArchiveStream
所以,基本上,你的功能背后的整个思考过程都是有缺陷的。您根本不应该拥有该功能。您只需要像这样制作其他功能:
public void UseMyArchiveStream()
{
using(var archive = ZipFile.OpenRead(_filepath))
{
var entry = archive.GetEntry("test.path");
using(var myStream = entry.Open())
{
//Do stuff
}
}
}
一种选择确实是保持archive
开放......但正如mjwills评论的那样,还有另一种方法可以做你想做的事,那就是给出UseMyArchiveStream
一个Action<>
orFunc<>
作为论点。这实际上意味着上面代码中的“Do stuff”注释被对您作为参数提供的任何函数的调用所取代:
public void UseMyArchiveStream(String zipPath, String entryName, Action<Stream, String> doStuff)
{
using (var archive = ZipFile.OpenRead(zipPath))
{
var entry = archive.GetEntry(entryName);
using (var myStream = entry.Open())
{
doStuff(myStream, entry.FullName);
}
}
}
用函数演示void SaveStreamToFile(Stream file, String filename)
:
UseMyArchiveStream(_filepath, "test.path", (str, nm) => SaveStreamToFile(str, nm));
使用Func<>
,您也可以创建一个提供返回值的重载。中的最后一个参数<>
始终是返回类型。但是您可以轻松地使用泛型来使其依赖于调用输入:
public T UseMyArchiveStream<T>(String zipPath, String entryName, Func<Stream, String, T> doStuff)
{
using (var archive = ZipFile.OpenRead(zipPath))
{
var entry = archive.GetEntry(entryName);
using (var myStream = entry.Open())
{
return doStuff(myStream, entry.FullName);
}
}
}
您可以以相同的方式调用它,仅使用返回值而不是返回值的函数void
。证明Boolean DostuffWithFile(Stream file, String entryName)
:
Boolean ok = UseMyArchiveStream(_filepath, "test.path", (str, nm) => DostuffWithFile(str, nm));
请注意,您调用的函数不必与参数的确切签名匹配。您可以通过这种调用方式完美地用本地数据替换缺少的参数。
证明Boolean DostuffWithFile(Stream file, String entryName, Boolean someOption, String outputFolder)
:
Boolean ok = UseMyArchiveStream(_filepath, "test.path", (str, nm) => DostuffWithFile(str, nm, true, _savePath));
只要需要提供的输入UseMyArchiveStream
只是=>
. 当然,你可以随心所欲地处理论点;你甚至可以只给函数整个ZipArchiveEntry
对象,甚至可能是 source ZipFile
,所以你可以用它做任何你想做的事情。
这种方法的唯一缺点是您实际上无法命名Action<>
or的组件Func<>
,因此,在这种情况下,您无法仅从函数签名中UseMyArchiveStream
知道String
给定的参数是否Func<Stream, String, T>
将接收entry.Name
or entry.FullName
。这同样适用于给出相同类型的多个参数;如果您有五个布尔选项,Func<>
您可能很难准确记住哪个是哪个,而不必每次都查看代码。所以一定要在函数注释中准确记录,以免以后混淆。