实现IDisposable(一次性模式)作为服务(类成员)

Disposable模式是基于每个类重新实现的模式。 所以,我一直在寻找一种概括它的方法。 几年前我遇到的问题是,即使你把它作为类本身实现,你也不能从一个Disposable实现和另一个类派生一个对象(C#不支持多inheritance)。

问题是, 如何实现一般方法来实现Disposable模式,这样您就不需要为实现IDisposable的类显式编写它?

以下是Visual Studio(VS 2015)为您生成的标准Disposable模式。

public class TestClass : IDisposable { #region IDisposable Support private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: dispose managed state (managed objects). } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } } // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. // ~DisposeTest() { // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. // Dispose(false); // } // This code added to correctly implement the disposable pattern. public void Dispose() { // Do not change this code. Put cleanup code in Dispose(bool disposing) above. Dispose(true); // TODO: uncomment the following line if the finalizer is overridden above. // GC.SuppressFinalize(this); } #endregion } 

我的实施

所以,这是我提出的解决方案。

 public class DisposeService where T : IDisposable { private readonly T _disposee; public Action ManagedAction { get; set; } public Action UnmanagedAction { get; set; } public DisposeService(T disposee, Action managedAction = null, Action unmanagedAction = null) { _disposee = disposee; ManagedAction = managedAction; UnmanagedAction = unmanagedAction; } private bool _isDisposed; public void Dispose(bool isDisposing) { if (_isDisposed) return; if (isDisposing && ManagedAction != null) { ManagedAction(_disposee); } var hasUnmanagedAction = UnmanagedAction != null; if (hasUnmanagedAction) { UnmanagedAction(_disposee); } _isDisposed = true; if (isDisposing && hasUnmanagedAction) { GC.SuppressFinalize(_disposee); } } } 

此类允许您为实现IDisposable的类创建DisposableService <>成员。 以下是仅有托管资源时如何使用它的示例。

 public class TestClass : IDisposable { protected readonly DisposeService DisposeService; private readonly SafeHandle _handle; public TestClass() { DisposeService = new DisposeService(this, ps => { if (_handle != null) _handle.Dispose(); }); _handle = new SafeFileHandle(IntPtr.Zero, true); } public void Dispose() { DisposeService.Dispose(true); } } 

这个怎么运作

  • DisposeService将在对象的Dispose上运行它的Dispose。
  • DisposeService的dispose将运行您在初始化时提供的Managed和Unmanaged Action(或在派生类中更新)。
  • 如果提供了UnmanagedAction,GC.SuppressFinalize将自动运行。
  • 始终确保将DisposableService <>创建为构造函数的第一个操作。

因此,这是一个将此服务与非托管资源一起使用的示例。

 public class TestClass : IDisposable { protected readonly DisposeService DisposeService; private readonly SafeHandle _handle; public TestClass() { DisposeService = new DisposeService(this, ps => { if (_handle != null) _handle.Dispose(); }, ps => { /* Free unmanaged resources here */ }); _handle = new SafeFileHandle(IntPtr.Zero, true); } public void Dispose() { DisposeService.Dispose(true); } ~TestClass() { DisposeService.Dispose(false); } } 

并且,从上面的类中创建派生类的示例。

 public class TestClassDerived : TestClass, IDisposable { private readonly SafeHandle _derivedHandle; public TestClassDerived() { // Copy the delegate for the base's managed dispose action. var baseAction = DisposeService.ManagedAction; // Update the managed action with new disposes, while still calling the base's disposes. DisposeService.ManagedAction = ps => { if (_derivedHandle != null) { _derivedHandle.Dispose(); } baseAction(ps); }; _derivedHandle = new SafeFileHandle(IntPtr.Zero, true); } } 

容易腻的柠檬挤。 保留对base的委托的引用,并将其作为派生类委托的一部分进行调用。

总体而言,应该更清洁,然后管理自2005年以来微软一直提供的blarg程序区…

编辑:我认为在构造函数中传递的’this’可能是一个问题。 但是,它似乎并不是: 将“这个”作为一个论点传递是不是一种坏习惯? 只需记住将null检查放在您的操作中,这样就不会尝试Dispose无效的东西。 🙂