如何在从另一个一次性类继承的类中实现一次性模式?

问题描述:

我经常在引用少量资源的简单类中使用一次性模式,但是我从来不必在从另一个一次性类继承的类上实现此模式,我开始有点困惑于如何释放整个资源。如何在从另一个一次性类继承的类中实现一次性模式?

我开始一点点的示例代码:

public class Tracer : IDisposable 
{ 
    bool disposed; 
    FileStream fileStream; 

    public Tracer() 
    { 
     //Some fileStream initialization 
    } 

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

    protected virtual void Dispose(bool disposing) 
    { 
     if (!disposed) 
     { 
      if (disposing) 
      { 
       if (fileStream != null) 
       { 
        fileStream.Dispose(); 
       } 
      } 

      disposed = true; 
     } 
    } 
} 

public class ServiceWrapper : Tracer 
{ 
    bool disposed; 
    ServiceHost serviceHost; 

    //Some properties 

    public ServiceWrapper() 
    { 
     //Some serviceHost initialization 
    } 

    //protected override void Dispose(bool disposing) 
    //{ 
    // if (!disposed) 
    // { 
    //  if (disposing) 
    //  { 
    //   if (serviceHost != null) 
    //   { 
    //    serviceHost.Close(); 
    //   } 
    //  } 

    //  disposed = true; 
    // } 
    //} 
} 

我真正的问题是:如何实现我的ServiceWrapper类中一次性模式,以确保当我将部署它的一个实例,它会处理在继承和基类中的资源?

谢谢。

我已经看到了这一点做了几个方面:

  1. 在派生类中重写的Dispose(BOOL处置),清理你的东西,然后调用基类的Dispose(BOOL处置)。这里的问题是基类已经有了门控变量并检查了需要复制的门控变量。

  2. 创建一个受保护的Cleanup方法,在基类中调用Dispose(bool disposing)来实际执行清理。派生类可以覆盖它,执行清理并调用基类Cleanup方法。这会使所有在基类中处理的检查都不必复制。

+0

第一种解决方案看起来很棒,但许多指导方针警告这种用法。处理布尔目的是通知Dispose已从Dispose()方法中调用。在这里,我们不能说不是这样,但是这是不正确的。 – Ucodia 2010-04-03 15:42:09

+1

我终于找到了一个CodeAnalysis规则,它为这种情况定义了一个精确的指南:http://msdn.microsoft.com/fr-fr/library/ms182330(VS.80).aspx这个指南完全符合你的第一个解决方案。 – Ucodia 2010-04-03 15:46:58

继承的类ServiceWrapper从实现IDisposable的类继承,所以SericeWrapper也实现了IDisposable。为了证明,新增了一个ServiceWrapper的实例。你会发现(使用intellisense)它也有一个Dispose()方法。

+0

是的我知道,但问题是它将调用ServiceWrapper类中的Dispose(bool disposing)方法,因此不会释放我的基类中的资源。如果我在调用base.Dispose()方法处理继承类时,我会遇到堆栈溢出问题。 – Ucodia 2010-04-03 15:17:23

看一看这篇博客文章由戴维·奥比昂:http://davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/

它增加了一些额外的代码父类,但在子类中做适当的清理变得相当简单。

+0

感谢这篇文章。这是daddyman提出的第二个解决方案的一个很好的例子。我想我会在下一次必须进行一次性课程时选择这种方式。实施起来要容易得多。再次感谢。 – Ucodia 2010-04-04 00:16:26

首先你有一些问题,你没有定义一个终结器,但你叫GC.Suppressfinalizer。 你也设置处置错误的方法,并且你的配置不是线程安全的。

我使用一个基本处置类实现IDispose以及其他辅助方法的主机。

public class Disposable : IDisposable 
{ 
    private object _lock = new object(); 

    ~Disposable() 
    { 
     try 
     { 
      Dispose(false); 
     } 
     catch 
     { 

     } 
    } 

    protected void ThrowIfDisposed() 
    { 
     if (IsDisposed) 
     { 
      throw new ObjectDisposedException(GetType().FullName); 
     } 
    } 

    public bool IsDisposed { get; private set; } 

    protected virtual void Dispose(bool disposing) 
    { 

    } 

    public void Dispose() 
    { 
     lock (_lock) 
     { 
      if (!IsDisposed) 
      { 
       Dispose(true); 
       IsDisposed = true; 
       GC.SuppressFinalize(this); 
      } 
     } 
    } 
}