如何将 "generic" C# 集合公开给 COM

How to expose "generic" C# collection to COM

我有一个 API,我开发了一个 C# 客户端,用于将 HTTP GET 请求转换为 C# 对象。

我已经在 VB6 中使客户端 COM 可见,因为我需要它,这里的问题是通用集合不能在 COM 上工作。我已经通过自己实现一个集合来“修复”这个问题,但它不是通用的。

这意味着我的每个 classes 都有一个名为 [Class]_Collection 的 class,这只是意味着我有没有通用 class.

的集合

这很好用,除了我们的 API 非常大,有很多不同的对象,所以如果我不必为我们的 [=] 中的每个 class 编写实现就好了25=].

我一直在试验我可以继承的通用基础 class 或通用接口,但如前所述,COM 不喜欢通用 classes。 我还需要一个 IDispatch 接口来公开功能,以便 class 函数在 VB6 中公开。

有没有一种方法可以让我为我的所有集合编写实现,并在需要的地方继承该功能?

泛型确实与 COM 不兼容,据我所知,没有办法绕过该限制。

我用作简单解决方法的方法是添加专门用于 COM-interop 目的的包装器属性。

示例:

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

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

这样做的好处是相当简单,实际上不复制任何数据,并且通过 COM 运行。然而,它显然不是类型安全的,因为在 VB6 中,SomeNumbersCOM 的条目看起来只是 object。但是 VB6 无论如何都不是特别安全的,所以这可能不是什么大问题。至少真正的强类型集合可以在 C# 中使用。 Obsolete 有助于执行此操作。

根据我的经验,类型安全性的轻微损失并不是真正的问题。您仍然可以在 VB 端断言正确的类型;例如,从 SomeNumbersCOM 列表中获取值时使用 Long 变量..

您不必添加太多不只是样板的代码。例如,您不必实际编写代码集合 classes 或复制它们的内部逻辑。


您可以创建一个完整的包装器 class,而不是将属性包装在同一个 class 中,这对于 C# 使用者来说会更简洁一些。

创建一个完全独立的 COM-visibility 包装器程序集(其中包含所有这些包装器 classes)将是强制不从 C# 端的其他地方使用包装器的更强大的方法。