如何在从另一个一次性类继承的类中实现一次性模式?
我经常在引用少量资源的简单类中使用一次性模式,但是我从来不必在从另一个一次性类继承的类上实现此模式,我开始有点困惑于如何释放整个资源。如何在从另一个一次性类继承的类中实现一次性模式?
我开始一点点的示例代码:
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类中一次性模式,以确保当我将部署它的一个实例,它会处理在继承和基类中的资源?
谢谢。
我已经看到了这一点做了几个方面:
在派生类中重写的Dispose(BOOL处置),清理你的东西,然后调用基类的Dispose(BOOL处置)。这里的问题是基类已经有了门控变量并检查了需要复制的门控变量。
创建一个受保护的Cleanup方法,在基类中调用Dispose(bool disposing)来实际执行清理。派生类可以覆盖它,执行清理并调用基类Cleanup方法。这会使所有在基类中处理的检查都不必复制。
继承的类ServiceWrapper从实现IDisposable的类继承,所以SericeWrapper也实现了IDisposable。为了证明,新增了一个ServiceWrapper的实例。你会发现(使用intellisense)它也有一个Dispose()方法。
是的我知道,但问题是它将调用ServiceWrapper类中的Dispose(bool disposing)方法,因此不会释放我的基类中的资源。如果我在调用base.Dispose()方法处理继承类时,我会遇到堆栈溢出问题。 – Ucodia 2010-04-03 15:17:23
看一看这篇博客文章由戴维·奥比昂:http://davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/
它增加了一些额外的代码父类,但在子类中做适当的清理变得相当简单。
感谢这篇文章。这是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);
}
}
}
}
第一种解决方案看起来很棒,但许多指导方针警告这种用法。处理布尔目的是通知Dispose已从Dispose()方法中调用。在这里,我们不能说不是这样,但是这是不正确的。 – Ucodia 2010-04-03 15:42:09
我终于找到了一个CodeAnalysis规则,它为这种情况定义了一个精确的指南:http://msdn.microsoft.com/fr-fr/library/ms182330(VS.80).aspx这个指南完全符合你的第一个解决方案。 – Ucodia 2010-04-03 15:46:58