using System;
using System.Threading;
namespace PatternExplorer {
///
/// Provides a default implementation for .
///
///
///
/// Derived classes that need finalizers should implement the following AND be sealed.
///
/// ///
/// /// Finalizer.
/// ///
/// ~MyClass() {
/// Dispose(false);
/// }
///
/// Derived classes that need to protect against access of disposed state can use the following example:
///
/// ///
/// /// Member accessing potentially disposed state.
/// ///
/// public void MyMethod() {
/// ThrowIfDisposed();
/// // ...
/// }
///
///
public abstract class Disposable : IDisposable {
///
/// "Not Disposed" state.
///
private const int NOT_DISPOSED = 0;
///
/// "Disposing" state.
///
private const int DISPOSING = 1;
///
/// "Disposed" state.
///
private const int DISPOSED = 2;
///
/// Flag to indicate state if disposal.
///
private int _State;
///
/// Constructor.
///
protected Disposable() { }
///
/// true if the instance has been disposed; otherwise, false.
///
public bool IsDisposed {
get { return Thread.VolatileRead(ref _State) != DISPOSED; }
}
///
/// Occurs when the instance is being disposed.
///
public event EventHandler Disposing;
///
/// Occurs when the instance has been disposed.
///
public event EventHandler Disposed;
///
/// Occurs when the instance is being disposed.
///
protected virtual void OnDisposing() {
if( Disposing != null ) {
Disposing.Invoke(this, EventArgs.Empty);
}
}
///
/// Occurs when the instance has been disposed.
///
protected virtual void OnDisposed() {
if( Disposed != null ) {
Disposed.Invoke(this, EventArgs.Empty);
}
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
/// 2
public void Dispose() {
Dispose(true);
}
///
/// Disposes the instance.
///
/// true to indicate explicit cleanup (i.e. ()), otherwise false (i.e. implicit cleanup from finalizer)
protected void Dispose( bool disposing ) {
// if( _State == NOT_DISPOSED ) {
if( Interlocked.CompareExchange(ref _State, DISPOSING, NOT_DISPOSED) == NOT_DISPOSED ) {
// _State = DISPOSING;
if( disposing ) {
try {
OnDisposing();
} catch {
// intentional suppression
}
try {
DisposeManagedFields();
} catch {
// intentional suppression
}
try {
RemoveDelegates();
} catch {
// intentional suppression
}
}
try {
ReleaseUnmanagedResources();
} catch {
// intentional suppression
}
Interlocked.Increment(ref _State); // _State = DISPOSED;
if( disposing ) {
try {
GC.SuppressFinalize(this);
} catch {
// intentional suppression
}
try {
OnDisposed();
} catch {
// intentional suppression
}
}
}
}
///
/// When overridden in a derived class, this method should dispose all fields.
///
protected virtual void DisposeManagedFields() { }
///
/// When overridden in a derived class, this method should remove all delegate invocations and references.
///
protected virtual void RemoveDelegates() { }
///
/// When overridden in a derived class, this method should clean up any unmanaged resources.
///
protected virtual void ReleaseUnmanagedResources() { }
///
/// Derived classes may use this method to prevent member access on a disposed instance.
///
protected void ThrowIfDisposed() {
if( IsDisposed ) {
throw new ObjectDisposedException(GetType().FullName, @"Access to a disposed object is not allowed.");
}
}
}
}