COM 互操作 (CCW) 中的重载 - IDispatch 名称包括后缀(_2、_3 等)
我有一个包含一些类的托管程序集,并且这些类具有重载方法。 我通过 .. 向 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)]
,我仍然可以以这种方式调用重载方法,从而避免了>参数数量错误或属性分配无效
错误。
我的问题是:这种行为 - 将数字后缀附加到成员名称 - 稳定吗? 记录在案? 可信?
I have a managed assembly containing a few classes, and those classes have overloaded methods. I expose the assembly to COM/IDispatch callers via
[ComVisible(true)]
..and also setting the proper Guid, on the assembly itself. I do not define an explicit interface for the COM interop. It's all done dynamically. I run regasm.exe /codebase
on the managed DLL and it registers it for COM interop.
When I run OleView, I can see the ProgId's of the various classes in the assembly. But, browsing into those ProgIds, and expanding IDispatch node, there is no TypeLib information for these classes.
Even so, from a script, I can invoke a method that accepts zero arguments or a method that accepts one argument. If there is also an overload that accepts more than one argument, I cannot invoke that method by name. The error I get, consistently, is
Microsoft VBScript runtime error: Wrong number of arguments or invalid property assignment: <methodname>
From this I understood that COM/IDispatch clients were not able to properly resolve overloaded methods on an object exposed via COM interop.
Then I added
[ClassInterface(ClassInterfaceType.AutoDual)]
...to each of the classes in question. After regasm.exe
on the DLL, I can see typelib information for each method, under the IDispatch node.
What I found is that overloaded methods automatically get a name that includes an appended suffix. MethodX will expose overloads in the auto-generated typelib assembly as MethodX, MethodX_2, MethodX_3, and so on.
And I found that by referencing the method names with those suffixes, I could invoke overloaded methods, although not with the common name.
More interestingly, if I then removed the [ClassInterface(ClassInterfaceType.AutoDual)]
from the classes, I could still invoke the overloaded methods in this way, thus avoiding the Wrong number of arguments or invalid property assignment
error.
My question is: is this behavior - appending numeric suffixes to the member names - stable? documented? dependable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
COM 不支持方法重载,因此 .NET COM Interop 层必须临时改进。 我不确定您所描述的名称修改是否在任何地方都有记录,但即使是这样,我也不认为使用它是一个好主意 - 对于 COM 用户来说,它仍然是相当不方便的 API。 如果您想将类公开给 COM,最好的方法是编写一个独特的 COM 友好的
[ComVisible]
接口,并隐藏类本身。 以 COM 友好的方式处理重载的正确方法是使用带有一些[Optional]
参数的单个方法(并委托给相应的 .NET 重载)。COM does not support method overloading, so .NET COM Interop layer has to improvise. I'm not sure if name mangling as you described as documented anywhere, but even if it is, I don't think that using it is a good idea - it's still pretty inconvenient API for COM users. If you want to expose your classes to COM, the best way is to write a distinct COM-friendly
[ComVisible]
interface, and hide the class itself. The correct way to handle overloads in a COM-friendly way would be have a single method with some[Optional]
arguments (and delegate to your corresponding .NET overloads).根据我的经验,让互操作生成
Method
、Method_1
、Method_2
等是正常且稳定的,但并不是真正理想的。 令人烦恼的是,重载没有跨越托管/非托管边界。 我没有让它在我的方法中任意添加数字后缀,而是尝试将 COM-Visible 方法重构为具有唯一名称的单独方法,以便 COM 使用者更清楚所调用的内容。In my experience, having interop generate
Method
,Method_1
,Method_2
, etc. is normal and stable but not really desirable. It's annoying that overloads don't cross the Managed/Unmanaged boundary. Instead of having it arbitrarily add a numeric suffix to my methods, I try to refactor the COM-Visible methods into separate methods with unique names so it's more obvious to the COM consumer what is being called.的,MSDN 上有记录:
是 更改它将是记录功能的“重大更改”,我想您可以信赖它是“稳定的”。 最大的缺点是方法名称取决于它们在源文件中定义的顺序。
但请注意,COM 支持可选参数,因此使用它们可能是重载的可行替代方案。 如果您需要添加重载以与库的旧 .NET 客户端二进制兼容,我发现以下模式很有用:
由于 COM 支持可选参数,因此
myMethod(string)
和myMethod(string, int)
会起作用。Yes, it's documented on MSDN:
Since changing it would be a "breaking change" of a documented feature, I guess you can rely on it being "stable". The big disadvantage is that your method names depend on the order in which they are defined in the source file.
Note, though, that COM supports optional arguments, so using them might be a viable alternative to overloads. If you need to add overloads to be binary-compatible to old .NET clients of your library, I found the following pattern to be useful:
Since COM supports optional parameters, both
myMethod(string)
andmyMethod(string, int)
will work.