COM互操作(CCW)中的重载 - IDispatch名称包括后缀(_2,_3等)

时间:2009-08-14 13:03:39

标签: .net com interop regasm typelib

我有一个包含几个类的托管程序集,这些类有重载方法。我通过

将程序集暴露给COM / IDispatch调用者
[ComVisible(true)]

..并在装配本身上设置适当的Guid。我没有为COM互操作定义显式接口。这一切都是动态完成的。我在托管DLL上运行regasm.exe /codebase并将其注册为COM互操作。

当我运行OleView时,我可以看到程序集中各种类的ProgId。但是,浏览这些ProgId并扩展IDispatch节点,这些类没有TypeLib信息。

即便如此,从脚本中,我可以调用接受零参数的方法或接受一个参数的方法。如果还有一个接受多个参数的重载,我不能按名称调用该方法。我得到的错误始终是

Microsoft VBScript runtime error: Wrong number of arguments or invalid property assignment:  <methodname>

据我所知,COM / IDispatch客户端无法正确解析通过COM互操作公开的对象上的重载方法。


然后我添加了

[ClassInterface(ClassInterfaceType.AutoDual)]

...对每个有问题的课程。在DLL上regasm.exe之后,我可以在IDispatch节点下看到每个方法的typelib信息。

我发现重载方法会自动获取包含附加后缀的名称。 MethodX将在自动生成的类型库组件中公开重载,如MethodX,MethodX_2,MethodX_3等。

我发现通过引用具有这些后缀的方法名称,我可以调用重载方法,尽管没有通用名称。

更有趣的是,如果我从类中删除[ClassInterface(ClassInterfaceType.AutoDual)],我可以仍然以这种方式调用重载方法,从而避免Wrong number of arguments or invalid property assignment错误。

我的问题是:这种行为 - 将数字后缀附加到成员名称 - 稳定吗?记录?可信?

3 个答案:

答案 0 :(得分:5)

COM不支持方法重载,因此.NET COM Interop层必须即兴创作。我不确定你所描述的名称是否在任何地方都有记录,但即使是这样,我也不认为使用它是一个好主意 - 对于COM用户来说它仍然是非常不方便的API。如果要将类公开给COM,最好的方法是编写一个独特的COM友好[ComVisible]接口,并隐藏类本身。以COM友好的方式处理重载的正确方法是使用一个带有[Optional]个{{1}}参数的方法(并委托相应的.NET重载)。

答案 1 :(得分:1)

根据我的经验,互操作生成MethodMethod_1Method_2等是正常且稳定的,但并不是真正可取的。令人讨厌的是,重载不会越过Managed / Unmanaged边界。我尝试将COM-Visible方法重构为具有唯一名称的单独方法,而不是任意向我的方法添加数字后缀,因此对于COM消费者来说,更明显的是被调用的内容。

答案 2 :(得分:1)

是的,它已在MSDN上记录:

由于更改它将是一个记录功能的“突破性变化”,我想你可以依靠它“稳定”。最大的缺点是您的方法名称取决于在源文件中定义它们的 order

但请注意,COM支持可选参数,因此使用它们可能是重载的可行替代方法。如果您需要将重载添加到库的旧.NET客户端二进制兼容,我发现以下模式很有用:

// used for binary-compatibility with .NET clients who currently use 
// the old, one-parameter version
[ComVisible(false)]
void myMethod(String oneParameter) {   
    ... 
}   

// since this is the first COM-visible version, it is assigned the "correct" name.
void myMethod(String oneParameter, int newParameter = 0) {
    ...
}

由于COM支持可选参数,myMethod(string)myMethod(string, int)都可以使用。