为什么ArrayList与COM Interop一起使用,但IList <T>不兼容?

Tim*_*ong 7 generics scripting com-interop

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

泛型,如IList<T>似乎没有工作.

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

Dan*_*mov 6

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

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

将集合公开为此问题ArrayList解决方案,您无法解决它.

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

COM从来没有"拥有" ArrayList,是的,但是它从来没有.NET Framework中的任何类,因为它本身不是框架.但是,某些.NET类型会进入导出的类型库,而有些则不会.那么.NET Framework类呢?嗯,ArrayList[ComVisible],List<T>现在,不是.

为什么?

COM 通过接口工作,接口定义语言没有关于泛型的线索,也不支持它们.支持COM的语言(如VB6或C++)不知道如何处理泛型.

如果有一种生成接口的方法List<T>,它将包含T在其中,因此尝试公开泛型类型基本上没有意义.可能的想象替代方案是:

  • 生成的接口为通用型"特定"的版本,例如IListOfString用于List<string>
  • 擦除泛型类型信息(很像Java在编译时所做的)并替换Tobject.

第一个选项不可行,因为T在编译时可能不知道具体类型(读取:反射),并且无论如何List<T>都没有[ComVisible]属性.

第二个选项实际上是可行的,因为您可以提供自己的类接口IListICollection属性:

[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
    ....
}
Run Code Online (Sandbox Code Playgroud)

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

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