COM 互操作 (CCW) 中的重载 - IDispatch 名称包括后缀(_2、_3 等)
Posted
技术标签:
【中文标题】COM 互操作 (CCW) 中的重载 - IDispatch 名称包括后缀(_2、_3 等)【英文标题】:Overloads in COM interop (CCW) - IDispatch names include suffix (_2, _3, etc) 【发布时间】:2010-11-19 15:34:42 【问题描述】:我有一个包含几个类的托管程序集,这些类具有重载方法。我通过
将程序集公开给 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 节点下看到每个方法的类型库信息。
我发现重载的方法会自动获得一个包含附加后缀的名称。 MethodX 将在自动生成的 typelib 程序集中公开重载为 MethodX、MethodX_2、MethodX_3 等。
我发现通过引用带有这些后缀的方法名称,我可以调用重载方法,尽管不能使用通用名称。
更有趣的是,如果我从类中删除[ClassInterface(ClassInterfaceType.AutoDual)]
,我可以仍然以这种方式调用重载方法,从而避免Wrong number of arguments or invalid property assignment
错误。
我的问题是:这种行为 - 将数字后缀附加到成员名称 - 稳定吗?记录在案?可信?
【问题讨论】:
【参考方案1】:COM 不支持方法重载,因此 .NET COM 互操作层必须即兴发挥。我不确定您所描述的名称修改是否在任何地方都有记录,但即使是这样,我也不认为使用它是一个好主意 - 对于 COM 用户来说,它仍然是相当不方便的 API。如果你想向 COM 公开你的类,最好的方法是编写一个独特的 COM 友好的[ComVisible]
接口,并隐藏类本身。以 COM 友好的方式处理重载的正确方法是使用带有一些 [Optional]
参数的单一方法(并委托给相应的 .NET 重载)。
【讨论】:
【参考方案2】:根据我的经验,让 interop 生成 Method
、Method_1
、Method_2
等是正常且稳定的,但并不是很理想。令人讨厌的是,重载不会跨越托管/非托管边界。我尝试将 COM-Visible 方法重构为具有唯一名称的单独方法,以便 COM 使用者更清楚所调用的内容,而不是让它任意添加数字后缀。
【讨论】:
【参考方案3】:是的,它在 MSDN 上有记录:
Advanced COM Interoperability: Exported Member Conversion由于更改它将是文档功能的“重大更改”,我想您可以相信它是“稳定的”。最大的缺点是您的方法名称取决于它们在源文件中定义的顺序。
但请注意,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)
都可以使用。
【讨论】:
注意:当使用 VB.NET 时,这种技术(两个重载只是可选参数不同)需要 VS 2012。以上是关于COM 互操作 (CCW) 中的重载 - IDispatch 名称包括后缀(_2、_3 等)的主要内容,如果未能解决你的问题,请参考以下文章