简体   繁体   中英

How to expose "generic" C# collection to COM

I have an API which I have developed a C# client for which converts HTTP GET requests into C# objects.

I have made the client COM visible as I need it in VB6, the issue here is that generic collections does not work over COM. I have made a "fix" for this by making my own implementation of a collection except it is not generic.

This means I have a class named [Class] _Collection for each of my classes, this just means I have a collection without the generic class.

This works well except our API is quite large with quite a few different objects, so it would be nice if I did not have to write the implementation for every class in our API.

I have been experiementing with a generic base class or generic interface which I can inherit, but as previously stated COM does not like generic classes. I also require an IDispatch interface to expose functionality so that the class functions are exposed in VB6.

Is there a way in which I can write the implementation for all my collections and just inherit that functionality everywhere it is needed?

Generics are indeed incompatible with COM, as far as I know there is no way around that restriction in itself.

The approach I've used as a simple workaround is to add wrapper properties specifically for COM-interop purposes.

Example:

[ComVisible(false)]
public List<int> SomeNumbers {get; set;}

[ComVisible(true)]
[Obsolete("Use this for COM interop only")]
public IList SomeNumbersCOM => SomeNumbers;

This has the benefit of being fairly simple, does not actually copy any data, and functions through COM. However it is obviously not typesafe since within VB6 the entries of SomeNumbersCOM will just appear to be object . But VB6 isn't especially typesafe anyway, so this may not really be a big problem. And at least the real strongly typed collection can be used within C#. The Obsolete helps to enforce this.

The mild loss of type safety hasn't been a real issue in my experience. You still can assert the correct type on the VB side; eg, use a Long variable when getting values out of the SomeNumbersCOM list..

You don't have to add very much code that isn't just boilerplate. eg, you don't have to actually code collection classes or replicate their internal logic.


Instead of wrapping properties in the same class, you could create an entire wrapper class, which would be a bit cleaner for the C# consumers.

Creating an entirely separate COM-visibility wrapper assembly (which contains all those wrapper classes) would be an even stronger way to mandate that the wrappers are NOT used from elsewhere on the C# side.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM