using System; using System.Runtime.InteropServices; namespace Vanara.InteropServices { /// Factory for creating objects. public static class ComReleaserFactory { /// Factory method to create a using type inference. /// The type of the object. /// The object. /// A instance. public static ComReleaser Create(TObj obj) where TObj : class => new ComReleaser(obj); } /// /// A safe variable to hold an instance of a COM class that automatically calls on disposal. /// /// The type of the COM object. /// public class ComReleaser : IDisposable where T : class { /// Initializes a new instance of the class. /// The COM object instance. /// obj /// Argument value must be a COM object. - obj public ComReleaser(T obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); if (!obj.GetType().IsCOMObject) throw new ArgumentException("Argument value must be a COM object.", nameof(obj)); Item = obj; } /// Initializes a new instance of the class. /// The COM object instance. /// obj /// Argument value must be a COM object and expose . public ComReleaser(object obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); if (!obj.GetType().IsCOMObject) throw new ArgumentException("Argument value must be a COM object.", nameof(obj)); Item = obj is T t ? t : throw new ArgumentException($"Object must expose the {typeof(T).Name} interface."); } /// Gets the COM object. /// The COM object. public T Item { get; private set; } /// Performs an implicit conversion from to . /// The COM object. /// The result of the conversion. public static explicit operator ComReleaser(T obj) => new ComReleaser(obj); /// Performs an implicit conversion from to . /// The instance. /// The result of the conversion. public static explicit operator T(ComReleaser co) => co.Item; /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. public void Dispose() { if (Item == null) return; Marshal.ReleaseComObject(Item); Item = null; } } }