C#使用IDisposable清理临时文件

Jim*_*mbo 9 c# idisposable interface

我有一个FileUploader类,可以选择给它一个zip文件,它提取到一个临时位置并返回文件路径.

根据我的理解,IDisposable在FileUploader类上实现接口并使用该Dispose方法删除所有临时文件会使该类在其引用脱离上下文后立即自行清理?

这似乎并非如此 - 任何人都可以解释我如何去实现我想要实现的目标吗?

更新
澄清一下,我的代码是:

    public ActionResult ImportFile()
    {
        FileUploader uploader = new FileUploader(ControllerContext, "file"); // where "file" is the posted form's file element

        uploader.SaveOrExtractFilesToTempLocation();

        foreach (string file in uploader.files)
        {
            try
            {
                 // do some stuff
            }
            catch (Exception err)
            {
                 // let the user know
            }
        }
        return View();
    }
Run Code Online (Sandbox Code Playgroud)

我试图在ImportFile()方法完成后让FileUploader删除所有临时文件

Mar*_*ell 7

"脱离背景"尚不清楚; 你必须这样做:

using(var file = new FileUploader(...)) {
    // do the work here
}
Run Code Online (Sandbox Code Playgroud)

没有using,没有特殊处理.然后编译器将其转换为以下内容:

var file = new FileUploader(...);
IDisposable tmp = file;
try {
    // do the work here
} finally {
    if(tmp != null) tmp.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

它是这个引起的确定性清理.


Oli*_*ich 7

您需要正确实现IDisposable.喜欢下面的课程.

using System.IO;

/// <summary>
/// Represents a temporary storage on file system.
/// </summary>
public sealed partial class TempStorage
     : IDisposable
{
    #region Constructor

    private TempStorage()
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="TempStorage"/> class.
    /// </summary>
    /// <param name="path">The path to use as temp storage.</param>
    public TempStorage(string path)
    {
        this.Path = path;
        this.Clear();
        this.Create();
    }

    #endregion

    #region Properties

    private string Path
    {
        get;
        set;
    }

    #endregion

    #region Methods

    private void Create()
    {
        try
        {
            if (!Directory.Exists(this.Path))
            {
                Directory.CreateDirectory(this.Path);
            }
        }
        catch (IOException)
        {
        }
    }

    public void Clear()
    {
        try
        {
            if (Directory.Exists(this.Path))
            {
                Directory.Delete(this.Path, true);
            }
        }
        catch (IOException)
        {
        }
    }

    #endregion

    #region IDisposable

    /// <summary>
    /// An indicator whether this object is beeing actively disposed or not.
    /// </summary>
    private bool disposed;

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Throws an exception if something is tried to be done with an already disposed object.
    /// </summary>
    /// <remarks>
    /// All public methods of the class must first call this.
    /// </remarks>
    public void ThrowIfDisposed()
    {
        if (this.disposed)
        {
            throw new ObjectDisposedException(this.GetType().Name);
        }
    }

    /// <summary>
    /// Releases managed resources upon dispose.
    /// </summary>
    /// <remarks>
    /// All managed resources must be released in this
    /// method, so after disposing this object no other
    /// object is beeing referenced by it anymore.
    /// </remarks>
    private void ReleaseManagedResources()
    {
        this.Clear();
    }

    /// <summary>
    /// Releases unmanaged resources upon dispose.
    /// </summary>
    /// <remarks>
    /// All unmanaged resources must be released in this
    /// method, so after disposing this object no other
    /// object is beeing referenced by it anymore.
    /// </remarks>
    private void ReleaseUnmanagedResources()
    {
    }

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            /* Release unmanaged ressources */
            this.ReleaseUnmanagedResources();

            if (disposing)
            {
                /* Release managed ressources */
                this.ReleaseManagedResources();
            }

            /* Set indicator that this object is disposed */
            this.disposed = true;
        }
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

然后在main方法中的using-block中使用类,如下所示:

using(TempStorage myStorage = new TempStorage("C:\temp")
{
    // rest of the main method here...
}
Run Code Online (Sandbox Code Playgroud)