C# 依赖于其他一次性物品的一次性物品

C# 依赖于其他一次性物品的一次性物品,c#,.net,C#,.net,我有一个基于字符串列表处理文件流的应用程序,字符串可以是磁盘上的文件,也可以是Zip文件中的文件。为了清理代码,我想重构打开文件的过程 我创建了一个返回文件内容流的方法,但由于该流依赖于ZipFile IDisposable,所以在我读取该流时,ZipFile已被释放,并引发异常 void Main() { using (var stream = OpenFileForImport("zipfile.zip;insidefile.txt")) new StreamRead

我有一个基于字符串列表处理文件流的应用程序,字符串可以是磁盘上的文件,也可以是Zip文件中的文件。为了清理代码,我想重构打开文件的过程

我创建了一个返回文件内容流的方法,但由于该流依赖于ZipFile IDisposable,所以在我读取该流时,ZipFile已被释放,并引发异常

void Main()
{
    using (var stream = OpenFileForImport("zipfile.zip;insidefile.txt"))
        new StreamReader(stream).ReadToEnd(); // Exception

    using (var stream = OpenFileForImport("outside.txt"))
        new StreamReader(stream).ReadToEnd(); // Works
}
public static Stream OpenFileForImport(string filePath)
{
    var path = Path.Combine(basefolder, filePath);

    if (path.Contains(";"))
    {
        var parts = path.Split(';');
        var zipPath = parts[0];

        //Error checking logic to ensure zip file exists and is valid...
        using (var zip = ZipFile.OpenRead(zipPath))
        using (var entry = zip.GetEntry(parts[1]))
        {
            //Error checking logic to ensure inside file exists within zip file.
            return entry.Open();
        }

    }

    var file = new FileInfo(path);
    if (file != null)
        return file.OpenRead();

    return null;

}

我可以从
zip
entry
声明中删除using子句,但我怀疑它们是否会被处理掉。当一次性文件依赖于其他一次性文件时,是否有适当的模式返回该文件?

您可能应该将文件从
ZipEntry
复制到
内存流中,以便有一个副本可供使用

    //Error checking logic to ensure zip file exists and is valid...
    using (var zip = ZipFile.OpenRead(zipPath))
    using (var entry = zip.GetEntry(parts[1]))
    {
        //Error checking logic to ensure inside file exists within zip file.
        MemoryStream stream = new MemoryStream();
        entry.Open().CopyTo(stream);
        stream.Seek(0, SeekOrigin.Begin); 
        return stream;
    }

不要直接返回流,而是返回一个一次性对象,该对象可以提供要处理的流,但在处理该流时会清理该流和其他从属资源:

public class NameToBeDetermined : IDisposable
{
    private ZipFile zip;
    public Stream Stream { get; }
    public NameToBeDetermined(ZipFile zip, Stream stream)
    {
        this.zip = zip;
        Stream = stream;
    }
    public void Dispose()
    {
        zip.Dispose();
        Stream.Dispose();
    }
}

然后返回它,而不是流本身。如果值得花时间的话,您可以将该包装器转换为
本身,它只是将所有
方法转发到组合流中,但这会在处理时做额外的工作。是否值得花时间创建更复杂的包装,而不是让调用者访问
属性,这取决于您。

假设文件甚至可以放入内存。在任意zip中访问任意文件的方法几乎肯定不能做出这样的假设。@Servy这是真的,但我猜测对
ReadToEnd
的调用应该是这样的。这只是一个示例调用,不一定代表每个调用(否则,该方法本身将读取整个内容并返回该内容,而不是流,如果您确实希望它将整个文件拉入内存,则应该这样做)。作为一般规则,如果返回流,我将在位置0处返回它。您可以返回一个自定义的
实现,该实现拥有可处置项,并在其自己的
Dispose
方法中处置它们。您需要使用封装并实现自己的类,该类使用Dispose接口。这就是我最终采用的解决方案你所说的“处理时做额外的工作”是什么意思?如果我处理所有包含的对象,包装器就位是否会带来任何风险?@MattMurrell“处理时做额外的工作”正在处理其他依赖对象。使用包装器您担心什么,您认为它会导致什么问题?