我可以在终结器中引用/使用COM对象吗?

本文关键字:COM 使用 对象 引用 我可以 | 更新日期: 2023-09-27 18:13:43

我有一个COM类型(使用tlbimp.exe创建)和一个c#类来包装这个对象。我想在c#包装器的终结器中执行一些清理。按照这里的指导原则,我可能会这样写:

public class MyClass : IDisposable
{
    private IMyComObject comObject;
    public MyClass()
    {
        comObject = new MyComObject();
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    ~MyClass()
    {
        Dispose(false);
    }
    protected virtual void Dispose(bool disposing)
    {
        // Be tollerant of partially constructed instances
        if (comObject != null)
        {
            comObject.Cleanup();
            // Account for object being disposed twice
            comObject = null;
        }
    }
    // Other bits go here...
}

我知道终结器可以以任何顺序运行,所以我不应该尝试使用任何实现终结器的对象,但是据我所知,生成的COM类型不实现终结器,所以上面应该没问题。

我还没有找到任何关于这方面的官方文档,但是,所以我的问题是在终结器中引用和使用COM对象是安全的吗?

我可以在终结器中引用/使用COM对象吗?

我创建了一个抽象的com包装器类,从中派生出所有的com包装器类。效果很好。我的原始代码是VB,因为我需要后期绑定(这是在c#引入dynamic类型之前)。我的应用程序的其余部分是用c#编写的。

public abstract class ComWrapper : IDisposable
{
    protected internal object _comObject;
    protected ComWrapper(object comObject)
    {
        _comObject = comObject;
    }
    #region " IDisposable Support "
    private bool _disposed = false;
    protected virtual void FreeManagedObjects()
    {
    }
    protected virtual void FreeUnmanagedObjects()
    {
        ReleaseComObject(_comObject);
    }
    private void Dispose(bool disposing)
    {
        if (!_disposed) {
            if (disposing) {
                FreeManagedObjects();
            }
            FreeUnmanagedObjects();
            _disposed = true;
        }
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected override void Finalize()
    {
        Dispose(false);
        base.Finalize();
    }
    #endregion
}

public static class Helpers
{
    public static void ReleaseComObject(ref object o)
    {
        if ((o != null)) {
            try {
                Marshal.ReleaseComObject(o);
            } catch {
            } finally {
                o = null;
            }
        }
    }
    public static string ToDotNetString(object comString)
    {
        if (comString == null) {
            return string.Empty;
        }
        string s = comString.ToString();
        ReleaseComObject(ref comString);
        return s;
    }
}