Tips for Designing COM-Friendly .NET Class Libraries
The design of COM Interoperability usually enables .NET class libraries to be usable from COM without any additional work or forethought by the library author. Still, there are some library-writing guidelines that, when followed, can greatly improve the COM-usability of .NET class libraries. Here are ten major guidelines:
Avoid creating members with names that conflict with method names of IUnknown or IDispatch, such as Release or Invoke. Such members are exposed to COM with mangled names to avoid collision.
Provide alternatives to parameterized constructors, because they are not directly exposed to COM.
Don't create APIs that rely on static members, because they are not easily accessible from COM.
Don't create APIs that rely on methods or properties of value types, because they are not directly exposed to COM.
Don't create APIs that rely on nested arrays, because the Interop marshaler does not support them.
Think twice before using overloaded methods, because they are exposed to COM with unintuitive and version-brittle names (suffixed with _2, _3, and so on).
Don't forget the benefits of interface-based programming. When defining public classes, it often makes sense to define a corresponding interface for the class to implement, and to always use the interface type rather than the class type in any public method, property, field, or event definitions. Also mark the class with ClassInterfaceAttribute and its ClassInterfaceType.None value to make the implemented interface the default.
Throw exception types defined in the mscorlib assembly whenever appropriate, because user-defined exceptions don't get the same special treatment by the Interop marshaler.
If you define a method that returns null (Nothing in VB .NET) to indicate failure, provide the option for it to throw an exception on failure instead. Because COM clients see S_OK returned whenever an exception isn't thrown, not throwing an exception may mistakenly lead them to believe the call succeeded when it really did not.
Use ComSourceInterfacesAttribute on classes that expose events, so they expose connection points to COM event sinks.