我必须在所有类上实现IDisposable吗,还是基类已足够?

7

我被告知需要处理我Entity Framework仓储类的实例,于是我创建了一个基类来强制进行这个实现。

我需要向专家确认:通过基类实现IDisposable是否可行?

请注意,仓储类没有类成员变量。

/// Sample repository.  Note that I return List<T> as IEnumerable, 
/// and I use IDisposable 
///
public class CompanyRepository : DisposableBase, ICompanyRepository
{
    public IEnumerable<CompanyDetail> GetOneCompany(int? CompanyID)
    {
        var t = from c in _entities.CompanyDetail
                where c.CompanyID == CompanyID.Value
                select c;
        return t.ToList();
    }
}

/// <summary>
/// Disposable implementation based on advice from this link:
/// from Http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
/// </summary>
public class DisposableBase : IDisposable
{
    protected TLSAdminEntities1 _entities;

    public DisposableBase()
    {
        _entities = new TLSAdminEntities1();
        disposed = false;
    }

    private bool disposed ;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                _entities.Dispose();
            }
        }
        this.disposed = true;
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}
4个回答

7
答案是“这取决于情况”。如果某个超类中的“Dispose()”方法已经足够,那么您肯定不需要在每个子类中重新实现它。 “超类”可能是基类;也可能是一个或多个子类。这取决于您分配了什么以及需要清理什么。在我看来...以下是MSDN的说法:

http://msdn.microsoft.com/en-us/magazine/cc163392.aspx

当您从可处理类型派生,并且该派生类型不引入任何新资源时,则无需执行任何特殊操作。基类型IDisposable实现将负责清理其资源,您的子类可以完全不知道详细信息。

换句话说,您不一定需要一遍又一遍地重新实现Dispose,但是...
然而,通常情况下会有一个子类包含需要清理的新资源。在这种情况下,您的类需要释放其资源,同时确保基本类型的资源也得到释放。通过重写 cleanup 方法来实现,释放您的资源,然后调用基本类型以清理其资源,如图6所示。

4

这取决于派生类是否有需要处理的资源。如果有特定于派生类的资源,仅在基类上实现IDisposable是不够的。


在我的情况下,我在继承的存储库类中没有任何本地内容。如果是这种情况,那么我的 CompanyRepository 实现是否就完成了? - makerofthings7
如果派生类中没有需要显式处理的内容,那么基类的实现可能已经足够了。 - James Johnson
1
只有基类应该实际实现 IDisposable。派生类通常应通过覆盖 Dispose(bool) 来添加其清理代码,而不是添加新的 IDisposable.Dispose() 实现。 - supercat
@supercat:这就是我所建议的,但我认为值得澄清的是,它应该从派生类中被覆盖。 - James Johnson
@JamesJohnson:在接口中,“实现”一词具有特定的技术含义。通常情况下,派生类需要包含处理“IDisposable”清理的代码,但应通过链接到基类实现的“IDisposable”,而不是定义新的实现来完成。 - supercat

1
通常来说,您必须在每个类中实现IDisposable,其中包含自身实现IDisposable的私有成员。这些资源必须被“释放”。我强烈建议您阅读关于IDisposable模式的这篇非常好的CodeProject文章。

0

使用基类进行处理是可以的。这里重要的是清理非托管资源,也就是关闭数据库连接。我认为最好使用像httpmodules或action filters这样的方式来连接到asp.net,以处理您的工作单元并对请求类型进行处理,但如果您只是确保在存储库实例上调用dispose,则使用一个处理实体框架上下文的基类是可以的(即使您使用过滤器/模块来处理它们,仍然可以使用这些存储库的基类)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接