【问题标题】:Why is it that ArrayList works with COM Interop, but IList<T> doesn't?为什么 ArrayList 可以与 COM 互操作一起使用,而 IList<T> 不能?
【发布时间】:2021-10-08 18:25:30
【问题描述】:

我注意到,如果我创建一个公开 ArrayList 的 .NET 组件,那么该 ArrayList 会通过 COM Interop 并且可以在脚本语言(例如 VBScript)中使用。

泛型,例如 IList&lt;T&gt; 似乎不起作用。

为什么会这样?有什么方法可以使泛型类型成功地通过 COM 互操作流到脚本引擎?

【问题讨论】:

  • 因为 COM 不支持泛型。看看thisthis 的问题。

标签: generics scripting com-interop


【解决方案1】:

.NET 2.0 中添加了泛型,COM 存在于 .NET 1.0 之前。
(并且是 .NET旨在取代的技术。)

COM 从来没有泛型,因此您不能公开它们。
两种 COM 语言(C++、VB6、Delphi)都没有泛型,因此您不能指望它们会被使用。
(嗯,C++ 有模板,但它们是完全不同的野兽,而 COM 只意味着 接口。)

将集合公开为ArrayListsolution 解决此问题,您无法解决它。

免责声明:我不是 COM 专家,所以其余答案大致基于我的猜测。

COM 从来没有“拥有”ArrayLists,没错,但是它从来没有任何 .NET Framework 中的类,因为它本身不是一个框架。但是,有些 .NET 类型会进入导出的类型库,而有些则不会。 .NET Framework 类呢?好吧,ArrayList[ComVisible],而 List&lt;T&gt; 不是。

为什么?

COM works via interfaces,而接口定义语言对泛型一无所知,也不支持它们。支持 COM 的语言(例如 VB6 或 C++)不知道如何处理泛型。

如果有办法为List&lt;T&gt; 生成一个接口,它不会在其中包含T,因此尝试公开泛型类型基本上没有意义。可能的想象替代方案是:

  • 为泛型类型生成“特定”版本的接口,例如IListOfStringList&lt;string&gt;
  • 擦除泛型类型信息(就像 Java 在编译时所做的那样)并将 T 替换为 object

第一个选项不可行,因为具体的T 类型在编译时可能不知道(阅读:反射),而且List&lt;T&gt; 无论如何都没有[ComVisible] 属性。

第二个选项实际上是可能的,因为你可以provide your own class interface with IList and ICollection properties

[ComVisible(true)]
public interface IPerson
{
    string Name { get;set;}
    DateTime Entered { get;set;}
    IList NickNamesList { get;}
    ICollection NickNamesCollection { get;}
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComDefaultInterface(typeof(IPerson))]
public class Person:IPerson
{
    [ComVisible(false)]
    public List<string> NickNames
    {
        get { return _NickNames; }
        set { _NickNames = value; }
    }
    private List<string> _NickNames = new List<string>();

    #region IPerson Members
    IList IPerson.NickNamesList
    {
        get { return this.NickNames; }
    }

    ICollection IPerson.NickNamesCollection
    {
        get { return this.NickNames; }
    }
    #endregion
    ....
}

这是一种解决方法,但不能回答您的问题。

我实际上想知道您是否可以从List&lt;string&gt; 派生您的StringList 类并将其标记为[ComVisible(true)]。你可能想检查一下。

【讨论】:

  • 我不能接受。 Microsoft 使 ArrayList 工作(COM 从来没有 ArrayLists) - 所以必须有可能以某种方式使其他类型工作。泛型在运行时具有具体类型。使 ArrayList 工作的机制是什么?
  • 我不是 COM 专家,但我编辑了答案以结合我的一些猜测。
  • 让我们假设后期绑定(IDispatch),看看这是否会对事物产生不同的看法。每个 .NET 类型在运行时都是具体类型,因此只要从 COM 组件使用后期绑定,它就应该能够“看到”从泛型派生的具体类型。鉴于 COM 具有自己的类型系统,因此需要在 .NET 类型和 COM 类型之间进行一些转换。我今天一直在阅读,现在我想知道是否可以使用自定义编组器将泛型类型“公开”给 COM?不过我对COM的了解真的很薄弱,所以我真的只是在黑暗中拍摄。
猜你喜欢
  • 2020-02-10
  • 2010-11-12
  • 1970-01-01
  • 2012-03-24
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多