Potresti dare un'occhiata a ex 28v = vs.103%29.aspx"> di Microsoft. ScheduledDisposable. Non l'ho mai usato, ma sembra che metterà in coda i tuoi oggetti per essere eliminati su un thread separato.
Ma se un pool è ciò che stai cercando, penso che funzionerà:
public interface IDisposableWrapper<TDisposable> : IDisposable where TDisposable : class, IDisposable
{
TDisposable Reference { get; }
}
public interface IDisposableWrapperFactory<TDisposable> where TDisposable : class, IDisposable
{
IDisposableWrapper<TDisposable> Create();
}
public sealed class ReusableDisposableFactory<TDisposable> : IDisposableWrapperFactory<TDisposable>, IDisposable
where TDisposable : class, IDisposable
{
readonly object padlock = new object();
Func<TDisposable> getReference;
Stack<TDisposable> stack;
int capacity;
public ReusableDisposableFactory(Func<TDisposable> getReference, int capacity)
{
if (getReference == null)
throw new ArgumentNullException("getReference");
this.stack = new Stack<TDisposable>(capacity);
this.capacity = capacity;
this.getReference = getReference;
}
bool IsDisposed { get { return stack == null; } }
void ThrowOnDisposed()
{
if (IsDisposed)
throw new ObjectDisposedException(GetType().Name);
}
sealed class ReusableDisposableWrapper : IDisposableWrapper<TDisposable>
{
ReusableDisposableFactory<TDisposable> factory;
TDisposable reference;
internal ReusableDisposableWrapper(ReusableDisposableFactory<TDisposable> factory, TDisposable reference)
{
if (factory == null)
throw new ArgumentNullException("factory");
this.factory = factory;
this.reference = reference;
}
public bool IsDisposed { get { return reference == null; } }
#region IDisposableWrapper<TDisposable> Members
public TDisposable Reference
{
get { return reference; }
private set { reference = value; }
}
#endregion
#region IDisposable Members
public void Dispose()
{
// Dispose of unmanaged resources.
Dispose(true);
// Suppress finalization. Since this class actually has no finalizer, this does nothing.
GC.SuppressFinalize(this);
}
void Dispose(bool disposing)
{
if (disposing)
{
// Free any other managed objects here.
var reference = Interlocked.Exchange(ref this.reference, null);
if (reference != null)
factory.DisposeReference(reference);
}
// Free any unmanaged objects here.
}
#endregion
public override string ToString()
{
var theReference = Reference;
if (IsDisposed || theReference == null)
return base.ToString() + ": Disposed";
else
return base.ToString() + ": " + theReference.ToString();
}
}
#region IDisposableWrapperFactory<TDisposable> Members
public IDisposableWrapper<TDisposable> Create()
{
lock (padlock)
{
ThrowOnDisposed();
TDisposable reference;
if (stack.Count > 0)
{
reference = stack.Pop();
}
else
{
reference = getReference();
}
return new ReusableDisposableWrapper(this, reference);
}
}
void DisposeReference(TDisposable reference)
{
lock (padlock)
{
if (reference == null)
return;
ThrowOnDisposed();
if (stack.Count < capacity)
{
stack.Push(reference);
}
else
{
reference.Dispose();
}
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
// Dispose of unmanaged resources.
Dispose(true);
// Suppress finalization. Since this class actually has no finalizer, this does nothing.
GC.SuppressFinalize(this);
}
void Dispose(bool disposing)
{
if (disposing)
{
lock (padlock)
{
if (!IsDisposed)
{
while (stack.Count > 0)
{
var reference = stack.Pop();
reference.Dispose();
}
stack = null;
getReference = null;
}
}
}
// Free any unmanaged objects here.
}
#endregion
public override string ToString()
{
string str = base.ToString();
if (!Monitor.TryEnter(padlock))
{
// Don't block for ToString()
str = str + ", locked.";
}
else
{
try
{
if (IsDisposed)
str = str + ", Disposed";
else
str = string.Format("{0}: {1} {2} cached", str, stack.Count, typeof(TDisposable).Name);
}
finally
{
Monitor.Exit(padlock);
}
}
return str;
}
}
Nota che la fabbrica stessa è usa e getta. Certamente sarei riluttante a usare questo per oggetti finalizzabili comunque.