namespace Vanara.PInvoke; /// A disposable context for which a delegate is called at entry and exit. /// /// This class can be used as follows: /// using (var ctx = new BeginEndEventContext(h => RegisterForEvents(out h), h => UnregisterForEvents(h))) /// { /// // Check to see if begin function succeeded /// if (!ctx.BeginSucceeded) /// return; /// /// // Do some work /// } /// // End function has been called /// public class BeginEndEventContext : IDisposable { private readonly Func? end; private bool disposedValue; private object? obj = null; /// Initializes a new instance of the class. /// The optional delegate to call when creating the context. /// The optional delegate to call when the context is disposed or goes out of scope. public BeginEndEventContext(Func? onBegin, Func? onEnd = null) : this(onBegin is null ? null : o => onBegin(), onEnd is null ? null : o => onEnd()) { } /// Initializes a new instance of the class. /// The optional delegate to call when creating the context. /// The optional delegate to call when the context is disposed or goes out of scope. public BeginEndEventContext(Func? onBegin = null, Func? onEnd = null) { end = onEnd; BeginSucceeded = onBegin?.Invoke(obj) ?? true; } /// Gets the return value of the onBegin delegate. public bool BeginSucceeded { get; } /// Gets the return value of the onEnd delegate. public bool EndSucceeded { get; private set; } /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } /// Releases unmanaged and managed resources. /// /// to release both managed and unmanaged resources; to release only unmanaged resources. /// protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { EndSucceeded = end?.Invoke(obj) ?? true; } obj = null; disposedValue = true; } } }