views:

33

answers:

1

Since COM objects hold non-memory resources but don't support IDisposable, I'm trying out some ideas to fake it. What do you think of my first attempt?

Public Function ComBlock(ByVal ParamArray comObjects As Object()) As IDisposable
    For i As Integer = 0 To comObjects.Length - 1
        If comObjects(i) Is Nothing Then Throw New ArgumentNullException("Null in parameter " & i)
        If Not Marshal.IsComObject(comObjects(i)) Then Throw New ArgumentException(comObjects(i).GetType.Name & " is not a COM object")
    Next

    Return New ComContext(comObjects)
End Function

Private Class ComContext : Implements IDisposable
    Private m_ComObjects As Object()
    Private m_Disposed As Boolean

    Sub New(ByVal comObjects As Object())
        m_ComObjects = comObjects
    End Sub

    Private Sub Dispose() Implements IDisposable.Dispose
        For Each item In m_ComObjects
            Marshal.FinalReleaseComObject(item)
        Next

        GC.SuppressFinalize(Me)
    End Sub

End Class
+1  A: 

I like the idea of where you're going. I'm more inclined to wrap a COM object I'm using in an IDisposable type, where the type exposes the COM object's public members (think: Adapter). The Dispose() method in your class will then handle the garbage collection of the COM object.

If you use a lot of COM objects, you could inherit from a base class to handle the disposal. I haven't tested this code at all, but this is generally what I'm thinking...

public abstract class COMAdapter : IDisposable {

    protected abstract object COMObject { get; }

    public void Dispose() {
        Marshal.FinalReleaseComObject(COMObject);
        GC.SuppressFinalize(this);
    }
}

public class ConcreteAdapter : COMAdapter {
    private YourCOMType _comObject;

    protected override object COMObject {
         get { return _comObject; }
    }
}
Sean H
I would use generics instead of inheritance for the concrete types, but I see your point.
Jonathan Allen