为什么 ArrayList 与 COM Interop 一起工作,但 IList<T> 与 COM Interop 一起工作?不是吗? [英] Why is it that ArrayList works with COM Interop, but IList&lt;T&gt; doesn&#39;t?

查看:20
本文介绍了为什么 ArrayList 与 COM Interop 一起工作,但 IList<T> 与 COM Interop 一起工作?不是吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到,如果我制作一个公开 ArrayList 的 .NET 组件,那么该 ArrayList 将通过 COM Interop 并在脚本语言(如 VBScript)中可用.

I've noticed that if I make a .NET component that exposes an ArrayList, then that ArrayList passes through COM Interop and is available in scripted languages such as VBScript.

泛型,例如 IList 似乎不起作用.

Generics, such as IList<T> do not seem to work.

这是为什么?有什么方法可以使泛型类型成功地通过 COM Interop 流向脚本引擎?

Why is this and is there any way to make a generic type successfully flow through COM Interop to a scripting engine?

推荐答案

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

Generics were added in .NET 2.0 and COM existed before .NET 1.0.
(And was the technology .NET aimed to replace.)

COM 从来没有泛型,因此你不能公开它们.
COM 语言(C++、VB6、Delphi)都没有泛型,所以你不能指望它们会被使用.
(好吧,C++ 有模板,但它们是完全不同的野兽,而 COM 仅意味着接口.)

COM never had generics, and therefore you cannot expose them.
Neither of COM languages (C++, VB6, Delphi) had generics so you can't expect them to be consumed.
(Well, C++ had templates but they are completely a different beast, and COM only meant interfaces.)

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

Exposing collections as an ArrayList is the solution to this problem, you can't work around it.

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

Disclaimer: I am no expert on COM so the rest of the answer is roughly based on my guesses.

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

COM never "had" ArrayLists, true, but so it never had any of the classes in .NET Framework, because it is not a framework itself. However, some of the .NET types get into the exported type libraries, and some don't. What about .NET Framework classes? Well, ArrayList is [ComVisible], and List<T> isn't.

为什么?

COM 通过接口工作,而接口定义语言对泛型和不支持他们.支持 COM 的语言,例如 VB6 或 C++,不知道如何处理泛型.

COM works via interfaces, and the Interface Definition Language has no clue about generics and doesn't support them. Languages that support COM, such as VB6 or C++, wouldn't know what to do with the generics.

如果有一种方法可以为 List 生成接口,那么它不会包含 T 所以本质上有尝试公开泛型类型毫无意义.可能的替代方案是:

If there was a way to generate an interface for List<T>, it would not contain T in it so there is essentially no point in trying to expose a generic type. Possible imaginary alternatives to this would be:

  • 为泛型类型生成特定"版本的接口,例如IListOfString for List
  • 擦除泛型类型信息(很像 Java 在编译时所做的)并将 T 替换为 object.
  • Generating a "specific" version of interface for a generic type, e.g. IListOfString for List<string>
  • Erasing generic type information (much like Java does on compilation) and replacing T with object.

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

The first option is not viable because the concrete T type may not be known at compilation (read: Reflection), and List<T> doesn't have a [ComVisible] attribute on it anyway.

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

The second option is actually sort of possible because you can 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
    ....
}

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

This is a workaround and doesn't answer your question though.

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

I am actually wondering if you could derive your StringList class from List<string> and mark it as [ComVisible(true)]. You may want to check that.

这篇关于为什么 ArrayList 与 COM Interop 一起工作,但 IList<T> 与 COM Interop 一起工作?不是吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆