2

我有一个包含几个类的托管程序集,这些类具有重载方法。我通过以下方式将程序集公开给 COM/IDispatch 调用者

[ComVisible(true)]

..并在程序集本身上设置正确的 Guid。我没有为 COM 互操作定义显式接口。这一切都是动态完成的。我regasm.exe /codebase在托管 DLL 上运行,它为 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)]

...到每个有问题的班级。在regasm.exeDLL 之后,我可以在 IDispatch 节点下看到每个方法的类型库信息。

我发现重载的方法会自动获得一个包含附加后缀的名称。MethodX 将在自动生成的 typelib 程序集中公开重载为 MethodX、MethodX_2、MethodX_3 等。

而且我发现通过引用带有这些后缀的方法名称,我可以调用重载方法,尽管不是使用通用名称。

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

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

4

3 回答 3

5

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

于 2009-08-15T02:04:24.070 回答
1

以我的经验,有 interop generate Method, Method_1,Method_2等是正常且稳定的,但并不是真正可取的。令人讨厌的是,重载不会跨越托管/非托管边界。我没有让它任意给我的方法添加数字后缀,而是尝试将 COM-Visible 方法重构为具有唯一名称的单独方法,以便 COM 使用者更清楚所调用的内容。

于 2009-08-15T01:40:10.053 回答
1

是的,它记录在 MSDN 上:

由于更改它将是已记录功能的“重大更改”,我想您可以依靠它“稳定”。最大的缺点是您的方法名称取决于它们在源文件中定义的顺序。

但请注意,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)使用。

于 2012-10-25T09:11:37.157 回答