为什么ArrayList与COM Interop协同工作,但IList< T>不? [英] Why is it that ArrayList works with COM Interop, but IList<T> doesn't?

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

问题描述

我注意到,如果我制作一个暴露ArrayList的.NET组件,那么ArrayList将通过COM Interop并且可以使用VBScript等脚本语言。



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



为什么会这样任何使泛型类型成功通过COM Interop流向脚本引擎的方法?

解决方案

泛型是在.NET 2.0中添加的, COM在.NET 1.0之前就已经存在了。

(并且是技术.NET 旨在替换。)



COM从不有泛型,因此你不能暴露它们。

COM语言(C ++,VB6,Delphi)都没有泛型,所以你不能指望它们被使用。

,C ++有模板,但它们完全是一个不同的野兽,而COM只意味着接口。)



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


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


COM永远不会有 ArrayList 因为它不是一个框架本身。但是,有些.NET类型会进入导出的类型库,有些则不会。那么.NET Framework类呢?那么, ArrayList [ComVisible] List< T>

为什么?

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



如果有一种方法可以为 List< T> ,它不会包含 T ,所以在尝试中基本没有意义揭示一个泛型类型。可能的想象替代方案是:


  • 为泛型类型生成一个特定版本的接口。 IListOfString 用于列表<字符串>

  • 擦除泛型类型信息Java在编译时执行)并用 object 替换 T


第一个选项不可行,因为具体的 T 类型在编译时可能不知道(read:Reflection), List< T> 无论如何都没有 [ComVisible] 属性。



第二个选项实际上是可能的,因为您可以为你自己的类接口提供 IList ICollection 属性

$ $ $ $ $ $ $ $ $ $ $ {$ b $ $ $ $ $ $ $ {
字符串名称{get; set;}
输入日期时间{get; set;}
IList NickNamesList {get;}
ICollection NickNamesCollection {ge t;}
}

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

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

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

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



我真的想知道你是否可以派生你的 StringList

列出< string> 并从code> class标记为 [ComVisible(true)] 。你可能想检查一下。


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.

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

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

解决方案

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

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.)

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

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

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.

Why?

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.

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:

  • 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.

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.

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.

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&lt; T&gt;不?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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