using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Reflection; using System.Diagnostics; using System.Threading; namespace Sleis.Utility { public interface IIsDisposed { bool IsDisposed { get; } } /// /// Basic functionality for an object implementing IDisposable /// public abstract class DisposableBase : IDisposable, IIsDisposed { private int _disposedCallCount; /// /// Safely dispose of an object without allowing exceptions to propogate. /// /// public static void SafeDispose(object inObject) { IDisposable disposable = inObject as IDisposable; if (disposable != null) { try { disposable.Dispose(); } catch (Exception) { } } } /// /// Safely dispose of an object without allowing exceptions to propogate, and set input /// reference to null. /// /// /// public static void SafeDispose(ref T ioObject) where T : class { object obj = ioObject; ioObject = null; SafeDispose(obj); } ~DisposableBase() { #if DEBUG if (!IsDisposed) { Assembly entryAssembly = null; try { entryAssembly = Assembly.GetEntryAssembly(); if (entryAssembly == null) { entryAssembly = Assembly.GetExecutingAssembly(); } } catch (Exception) { } DebugUtility.CheckDebuggerBreak(); } #endif // DEBUG // Do not re-create Dispose clean-up code here. // Calling Dispose(false) is optimal in terms of // readability and maintainability. Dispose(false); } /// /// IsDisposed /// public bool IsDisposed { get { return (_disposedCallCount < 0); } } /// /// Implement IDisposable. /// Do not make this method virtual. /// A derived class should not be able to override this method. /// public void Dispose() { Dispose(true); // Take yourself off the Finalization queue // to prevent finalization code for this object // from executing a second time. GC.SuppressFinalize(this); } /// /// Dispose(bool disposing) executes in two distinct scenarios. /// If disposing equals true, the method has been called directly /// or indirectly by a user's code. Managed and unmanaged resources /// can be disposed. /// If disposing equals false, the method has been called by the /// runtime from inside the finalizer and you should not reference /// other objects. Only unmanaged resources can be disposed. /// /// protected virtual void Dispose(bool inIsDisposing) { // Check to see if Dispose has already been called. if (Interlocked.Decrement(ref _disposedCallCount) == -1) { OnDispose(inIsDisposing); } } /// /// This is the method to override in your subclass. /// protected abstract void OnDispose(bool inIsDisposing); } }