2

I application that uses a a Interop Com Object. Therefore I had written a wrapper class, to do the freeing in the dispose or if this is not done in the finalizer. So I can use the using keyword, to ensure a freeing is done.

Is using this pattern a good way? Or is there even a class in the Framework that is doing this for me?

    class ComWrapper<T> : IDisposable
    {
        private readonly T comObject;

        private bool disposed = false;

        public ComWrapper(T comObject)
        {
            this.comObject = comObject;
        }

        ~ComWrapper()
        {
            this.Dispose(false);
        }

        public T ComObject
        {
            get
            {
                return this.comObject;
            }
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Dispose(bool disposing)
        {
            if (this.disposed)
            {
                return;
            }

            Marshal.FinalReleaseComObject(this.comObject);
        }
    }
sschoof
  • 1,531
  • 1
  • 17
  • 24
  • 1
    Your approach is fine. There is no class in framework which does this for you. You forgot to set `disposed` field to true after disposing the com object. `Dispose(bool)` should be protected and virtual (if inheritance is possible). – Sriram Sakthivel May 03 '15 at 12:12
  • Possible duplicate of: http://stackoverflow.com/questions/635839/best-way-to-access-com-objects-from-c-sharp – S.Spieker May 03 '15 at 12:15
  • No, this is fundamentally broken code and it can only work for very simple COM object models. I'm a bit worn out from talking programmers out of this mistake, just [read this blogpost](http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx) from guys that have done this a lot. – Hans Passant May 03 '15 at 14:55
  • I have some simple Com Objects for a API to a legacy System. If ever happen the API would be rewritten in .NET in one step. – sschoof May 04 '15 at 11:04

1 Answers1

0

I personally wouldn't recommend this because it seems somewhat pointless. But, I would recommend having a static class called Utility, with this method:

    public static void disposeComObject<T>(ref T comObject)
    {
       if(Marshal.IsComObject(comObject) && comObject != null)
       {
           //You need to save the object
           if(typeof(T) == typeof(Microsoft.Office.Interop.Excel.Workbook))
           {
                ((Microsoft.Office.Interop.Excel.Workbook))comObject.Save();
                ((Microsoft.Office.Interop.Excel.Workbook))comObject.Close();
           }

           //You need to save the object
           if(typeof(T) == typeof(Microsoft.Office.Interop.Excel.Application))
           {
                ((Microsoft.Office.Interop.Excel.Application))comObject.Quit();
           }

           Marshal.ReleaseComObject(comObject);
           comObject = null;
       }
    }

Now From Code, you can call this like so

     ...
     Microsoft.Office.Interop.Excel comObject = null;
     try{
        //Open comObject
        //Here I would call some functions, and have nested exceptions
     }
     catch(nestedException err)
     {
          //Handle at your discretion
     }
     finally{
          Utility.disposeComObject(ref comObject);
     }

This is specific to the Excel Namespace, but adjusting it should be easy enough.

Jaime Reynoso
  • 146
  • 1
  • 8