【问题标题】:Which method overload will be accessible from VBScript? [duplicate]VBScript 可以访问哪些方法重载? [复制]
【发布时间】:2016-08-28 08:09:07
【问题描述】:

System.Collections.ArrayListComVisible(true)。它包含IndexOf 的三个重载(参见here):

public virtual int IndexOf(Object value)
public virtual int IndexOf(Object value, int startIndex)
public virtual int IndexOf(Object value, int startIndex, int count)

从 VBScript 中,只能访问第二个重载:

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

'oList.IndexOf "foo"        'Error: Invalid procedure call or argument: 'IndexOf'
 oList.IndexOf "foo", 0
'oList.IndexOf "foo", 0, 1  'Error: Wrong number of arguments or property assignment was not valid: 'IndexOf'

'Overloading a method in com visible dll'Hans Passant 解释说 程序集中存在重载方法,但无法从脚本中获取它们 dispid,因此打电话给他们。这似乎意味着一种方法可能会成功。

  • 我能否从 ArrayList 源(或其他地方)确定可以访问哪个方法?管理这个选择过程的规则是什么?
  • 为什么情况一和三的错误消息不同?

【问题讨论】:

  • here(MSDN) 所述,当重载方法暴露给 COM 客户端时,只有第一个重载方法保留其名称。我不知道为什么不是这样,除非您链接中提供的代码不准确...
  • 就像@Pikoh 说的只有第一个重载保留了名称(Hans 也指出了这一点——“类型库导出器通过重命名重载方法来解决这个问题,它将是Write_2()。 ") 你为什么不试试oList.IndexOf_2 "foo", 0oList.IndexOf_3 "foo", 0, 1
  • 其实所有的方法都是暴露的。例如,您可以使用 :oList.IndexOf_3 "foo" 访问一个参数覆盖,或者使用 oList.IndexOf_2 "foo", 0, 1 访问 3 个参数
  • @Lankymart 谢谢,我正在考虑。事实证明,我的问题是一个糟糕的问题,因为它基于一个错误的假设。尽管如此,答案还是很有帮助的,而且总的来说似乎很有用。由于这是更新您的闲聊评论,因此我将在 24 小时内将其删除,以便为其他观众清理 cmets。感谢您的支持。

标签: c# vbscript overloading


【解决方案1】:

简答:全部。


我们来分析一下@hans-passant写了什么;

AnswerOverloading a method in com visible dll
COM 不支持成员重载,每个名称必须是唯一的。 IDispatch::GetIDsOfNames() 不可避免的副作用。脚本解释器用来将脚本代码中使用的“Write”转换为 dispid 的函数。该方法仍然存在,只是没有办法让GetIDsOfNames() 返回它的dispid。 类型库导出器通过重命名重载方法解决了这个问题,它将是Write_2()

分为两部分

  1. 解释IDispatch::GetIDsOfNames() 的行为
  2. 类型库导出器如何解决唯一性问题。

并不是说它们不可用,相反,它们已被重命名以避免IDispatch::GetIDsOfNames() 在将DISPID 分配给方法名称时所具有的唯一性约束。

所以所有三个重载都可用,只需使用以下格式重命名

oList.IndexOf
oList.IndexOf_2
oList.IndexOf_3

注意:没有IndexOf_1,因为第一个重载始终采用原始方法名称,后续重载从_2 开始。

取决于类型库导出器如何重命名重载将取决于哪个使用哪一组参数,解决此问题的唯一方法是反复试验。

快速尝试测试

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

oList.Add "bar"
oList.Add "foo"

WScript.Echo oList.IndexOf("foo", 0)
WScript.Echo oList.IndexOf_2("foo", 0, 1)
WScript.Echo oList.IndexOf_3("foo")

输出:

1
-1
1

为什么这两个语句会失败并出现不同的错误?

如果我们回到你原来的例子

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

'oList.IndexOf "foo"        'Error: Invalid procedure call or argument: 'IndexOf'
 oList.IndexOf "foo", 0
'oList.IndexOf "foo", 0, 1  'Error: Wrong number of arguments or property assignment was not valid: 'IndexOf'

由于 VBScript 评估方法签名的方式,语句 1 和 3 因不同的错误而失败。上例中正确的签名接受两个参数,所以第一个语句;

oList.IndexOf "foo"

将失败,因为唯一匹配的签名有两个参数,而不是一个因此错误;

无效的过程调用或参数:'IndexOf'

第三条语句

oList.IndexOf "foo", 0, 1

包含一个比预期签名多一个参数,因此它不是找不到匹配项而是找到一个匹配项;

错误数量的参数或属性分配无效:'IndexOf'

因为参数的数量超过了方法签名 IndexOf(arg, arg) 所期望的数量。


有用的链接

【讨论】:

    【解决方案2】:

    重载有编号的别名:

    >> Set al = CreateObject("System.Collections.ArrayList")
    >> al.Add "poo"
    >> al.Add "foo"
    >> WScript.Echo al.IndexOf("poo", 0)
    >>
    0
    >> WScript.Echo al.IndexOf("poo", 1)
    >>
    -1
    >> WScript.Echo al.IndexOf_1("foo")
    >>
    Error Number:       438
    Error Description:  Object doesn't support this property or method
    >> WScript.Echo al.IndexOf_2("foo")
    >>
    Error Number:       5
    Error Description:  Invalid procedure call or argument
    >> WScript.Echo al.IndexOf_3("foo")
    >>
    1
    >>
    

    我通过反复试验来解决问题;可能有文档或内省工具可用于更科学的方法。

    【讨论】:

    • 索引从_2开始第一个重载总是原来的名字没有_1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2019-06-17
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 2011-09-07
    相关资源
    最近更新 更多