使用IDisposable从磁盘删除文件

时间:2016-04-29 21:10:31

标签: c# .net idisposable system.io.file

我有一种情况需要将上传的HttpPostedFile保存到服务器的磁盘,提供一些代码的完整路径,这些代码将对磁盘上的文件执行某些操作,然后删除该文件。我决定使用代理来处理该文件。代理将文件的详细信息抽象为磁盘,并在不再使用后将其删除。我在代理中实现了IDisposable,以便将保存的文件视为非托管资源,并确保在某些时候删除它。当然,每次我尝试实现IDisposable时,我都会仔细检查模式并发现有关该主题的数十个问题和文章,涵盖所有最复杂的实现。

我认为大多数这些实现对我所需要的都是过度的,所以我更简单地实现了它。我班上的人数不多;只保存文件和一些公共字符串,以允许通过其文件路径访问保存的文件。有一个显式删除文件的Delete方法和一个Dispose方法,如果客户端代码没有,则调用Delete。最后还有一个终结器只能调用Dispose。课程是密封的。没有成员自己实现IDisposable。没有可观的托管资源。根据我的估计,没有必要进一步干预垃圾收集,因为唯一需要发生的重要事情就是删除文件。

所以我的问题是这些:

  1. 以这种方式处理保存和删除“临时”文件有什么本质上的错误吗?
  2. 我的以下IDisposable实现是否有任何问题,考虑到我不需要打扰托管资源清理。
  3. 请注意,在我的用例中,必须将文件保存到磁盘以获取另一段代码才能使用它,并且文件需要使用其文件路径访问,而不是通过传递流或类似的东西。

    public sealed class TempFileProxy : IDisposable
    {
        private bool disposed;
    
        public TempFileProxy(HttpPostedFile httpPostedFile)
        {
            this.disposed = false;
            this.FileName = httpPostedFile.FileName;
            this.Directory = AppSettings("TempFileDirectory");
            this.FullPath = $@"{this.Directory}\{this.FileName}";
    
            httpPostedFile.SaveAs(this.FullPath);
        }
    
        ~TempFileProxy()
        {
            this.Dispose();
        }
    
        public string FullPath { get; }
    
        public string Directory { get; }
    
        public string FileName { get; }
    
        public void Dispose()
        {
            if (this.disposed)
            {
                return;
            }
    
            this.disposed = true;
            this.Delete();
        }
    
        public void Delete()
        {
            if (File.Exists(this.FullPath))
            {
                File.Delete(this.FullPath);
            }
        }
    }
    

2 个答案:

答案 0 :(得分:1)

使用IDisposable实现删除临时文件没有任何问题。但是,在删除它时要更加小心 - 您不希望在此操作期间抛出异常(例如,因为文件正在使用中)。此外,如果已使用常规Dispose调用处置了对象,则禁止终结器:

~TempFileProxy() { 
    Dispose(false);
}

public void Dispose() { 
    Dispose(true); 
}

private void Dispose(bool disposing)
{
    if (disposing)
    {
        GC.SuppressFinalize(this);                
    }
    if (this.FullPath != null)
    {
        try { 
            File.Delete(this.FullPath); 
        }
        catch { }
        this.FullPath = null;
    }
}

答案 1 :(得分:1)

我有几个问题:

1)我遇到了File.Exists在某些外部设备上失败的问题。我已经达到了这个目的,我只是尝试使用该文件并捕获异常,如果它被抛出。

2)File.Delete可以抛出。 2a)文件正在被某些东西使用。 2b)留下了一个幻影锁。 (Windows 8 XPS查看器,我正在看着你!) 2c)网络问题。