Skip to content

Instantly share code, notes, and snippets.

@earthengine
Last active August 29, 2015 14:24
Show Gist options
  • Save earthengine/d0bcd2b46a0321628fe3 to your computer and use it in GitHub Desktop.
Save earthengine/d0bcd2b46a0321628fe3 to your computer and use it in GitHub Desktop.
Sometimes we need a disposable object to build a lazy value. If the lazy value was never accessed we need a way to dispose the object used for evaluation. This is a wrapper that will help on this
/// <summary>
/// A simple wrapper of a <see cref="Lazy"/> type that require a <see cref="IDisposable"/> object
/// to evaluate its value. The resulting object is also disposable.
///
/// Note: provides only 3 constructors. The 3 of <see cref="Lazy"/> that depends on the default
/// constructure does not make sense here.
/// </summary>
/// <typeparam name="T">The type of the disposable object</typeparam>
/// <typeparam name="R">The type of the lazily evaluated value</typeparam>
public class DisposableLazy<T, R> : IDisposable where T:IDisposable
{
private Lazy<R> value;
private IDisposable parameter;
private DisposableLazy(T parameter, Lazy<R> value)
{
this.parameter = parameter;
this.value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="LazyDisposable<T>"/> class.
/// When lazy initialization occurs, the specified initialization function
/// and initialization mode are used.
/// </summary>
/// <param name="valueFactory">
/// The delegate that is invoked to produce the lazily initialized value when it is needed.
/// It is supposed that a disposable object will be required as its parameter.
/// </param>
/// <param name="parameter">
/// The disposable object to be passed to the value factory delegate.
/// If the value was never evaluated, this parameter object shall be disposed as well.
/// </param>
public DisposableLazy(Func<T, R> valueFactory, T parameter) :
this(parameter, new Lazy<R>(() => valueFactory(parameter)))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LazyDisposable<T>"/> class.
/// When lazy initialization occurs, the specified initialization function
/// and initialization mode are used.
/// </summary>
/// <param name="valueFactory">
/// The delegate that is invoked to produce the lazily initialized value when it is needed.
/// It is supposed that a disposable object will be required as its parameter.
/// </param>
/// <param name="parameter">
/// The disposable object to be passed to the value factory delegate.
/// If the value was never evaluated, this parameter object shall be disposed as well.
/// </param>
/// <param name="isThreadSafe">
/// true to make this instance usable concurrently by multiple threads;
/// false to make this instance usable by only one thread at a time.
/// </param>
public DisposableLazy(Func<T, R> valueFactory, T parameter, bool isThreadSafe):
this(parameter, new Lazy<R>(() => valueFactory(parameter), isThreadSafe))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DisposableLazy<T>"/> class
/// using the specified initialization function and thread-safety mode.
/// </summary>
/// <param name="valueFactory">
/// The delegate that is invoked to produce the lazily initialized value when it is needed.
/// It is supposed that a disposable object will be required as its parameter.
/// </param>
/// <param name="parameter">
/// The disposable object to be passed to the value factory delegate.
/// If the value was never evaluated, this parameter object shall be disposed as well.
/// </param>
/// <param name="mode">
/// One of the enumeration values that specifies the thread safety mode.
/// </param>
public DisposableLazy(Func<T, R> valueFactory, T parameter, LazyThreadSafetyMode mode)
:this(parameter, new Lazy<R>(() => valueFactory(parameter), mode))
{
}
/// <summary>
/// See <see cref="Lazy<T>.IsValueCreated"/>
/// </summary>
public bool IsValueCreated { get { return value.IsValueCreated; } }
/// <summary>
/// See <see cref="Lazy<T>.Value"/>
/// </summary>
public R Value { get { return value.Value; } }
/// <summary>
/// Dispose the parameter
/// </summary>
public void Dispose()
{
using (parameter)
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment