为什么ArrayList与COM Interop一起使用,但IList <t>不支持?</t>

时间:2011-08-09 22:31:20

标签: generics scripting com-interop

我注意到如果我创建一个公开ArrayList的.NET组件,那么该ArrayList将通过COM Interop并以脚本语言(如VBScript)提供。

泛型,例如IList<T>似乎不起作用。

为什么这样,是否有任何方法可以使通用类型成功地通过COM Interop流向脚本引擎?

1 个答案:

答案 0 :(得分:6)

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

COM从来没有使用泛型,因此你不能暴露它们 COM语言(C ++,VB6,Delphi)都没有泛型,所以你不能指望它们被消费。
(好吧,C ++有模板,但它们完全是一个不同的野兽,COM只是意味着接口。)

将集合公开为ArrayList是此问题的solution,您无法解决此问题。

  

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

COM永远不会“拥有”ArrayList s,但是因此它从未在.NET Framework中拥有任何类,因为它本身不是框架。但是,某些.NET类型会进入导出的类型库,而有些则不会。那么.NET Framework类呢?好吧,ArrayList[ComVisible]List<T>不是。

为什么?

COM works via interfaces,接口定义语言没有关于泛型的线索,也不支持它们。支持COM的语言(如VB6或C ++)不知道如何处理泛型。

如果有一种方法可以为List<T>生成一个接口,那么中包含T,因此尝试公开泛型类型基本没有意义。可能的想象替代方案是:

  • 为通用类型生成“特定”版本的接口,例如IListOfString
  • List<string>
  • 删除泛型类型信息(非常类似于编译时的Java)并将T替换为object

第一个选项不可行,因为在编译时可能不知道具体的T类型(读取:反射),并且List<T>无论如何都没有[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
    ....
}

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

我实际上想知道您是否可以从StringList派生List<string>课程并将其标记为[ComVisible(true)]。你可能想检查一下。

相关问题