C# Interoperability – Writing .NET Libraries with COM Limitations

ccominteroperability

I came across this interesting article: How I Came to Love COM Interoperability on CodeProject, which got me thinking…

The author argues that they do not want any COM-ities in their .NET library because it takes away from the beauty of their .NET library. Instead, they'd rather write a separate Interop library that exposes their .NET library to COM. This Interop library would handle the fact that COM doesn't support Constructors with Parameters, Overloaded Methods, Generics, Inheritance, Static Methods, etc.

And while I think that is very novel, doesn't it just complect the project?

  • Now you need to unit test your .NET library AND an Interop library.
  • Now you need to spend time figuring out how to work around your beautiful .NET library and expose it to COM.
  • You need to, effectively, double or triple your class count.

I can certainly understand if you need your library to support both COM and non-COM. However, if you only intend to use COM does this sort of design bring any benefits that I don't see? Do you only gain the benefits of the C# language?

Or, does it make versioning your library easier by providing you a wrapper? Does it make your Unit Tests run faster by not requiring the use of COM?

Best Answer

However, if you only intend to use COM does this sort of design bring any benefits that I don't see?

This snippet of your question is the most important part of your design decision here, and the answer is (as always) it depends.

If you only intend to use the library via COM Interop, then you should design the entire system with this in mind. There is no reason to triple the line count. The more LoC in the system, the more defects it will have. You should therefore design your system to only use COM compatible functionality.

However, I can't think of a good reason to restrict the use of a .Net library to COM. Why wouldn't you want to be able to use the assembly in other .Net code? It makes little sense to limit yourself this way.

I have some experience with this, so I will share how I have handled it. Its certainly not ideal. I have made some trade offs. I only use a facade for COM classes (interfaces really) that are incompatible with the newer .Net idioms, otherwise, I directly expose the .Net interface to COM. This basically means that I use a facade for any interface that uses generics. Generics are the only thing I've come across that are just simply incompatible. Unfortunately, this means a facade for anything that returns an IEnumerable<T>, which is fairly common.

However, this isn't nearly as bad as it seems to be, because your facade class inherits from your .Net class and implements a specific Interop interface. Something like this.

namespace Company.Product.Feature
{
    public class MyClass : INetInterface 
    {
        // lots of code
    }
}

namespace Company.Product.Interop
{
    public class MyClass : Feature.MyClass, IComInterface
    {
        // over ride only the  incompatible properties/methods
    }
}

This keeps your duplicate code to an absolute minimum and protects your COM interface from "unintentional" changes. As your core class/interface change, your adapter class has to over ride more methods (or break the interface and bump the major version number). On the other hand, not all of your Interop code is stored in the Interop namespace, which can lead to a confusing file organization. Like I said, it's a trade off.

For a full blown example of this, you can browse through the SourceControl and Interop folders of my repo. ISourceControlProvider and GitProvider will be of particular interest.