使用显式接口实现时,如何select将哪个成员导出到COM?

How to select which member is exported to COM when using explicit interface implementation?

如果我的 class 实现 IEnumerable,我可以使用 VBScript 的 For Each 循环:

[ComVisible(true)]
[ProgId("Whosebug.MyIssues")]
[Guid("7D392CB1-9080-49D0-B9CE-05B214B2C448")]
public class MyIssue : IEnumerable
{
  readonly List<string> issues = new List<string>(new string[] { "foo", "bar" });

  public string this[int index]
  {
    get { return issues[index]; }
  }

  public IEnumerator GetEnumerator()
  {
    return issues.GetEnumerator();
  }
}


Dim o : Set o = CreateObject("Whosebug.MyIssues")

Dim i
For Each i In o
  WScript.Echo i
Next

如果我将接口更改为 IEnumerable<string>(因此 C# 的 foreach 循环使用 string 而不是 object):

public class MyIssue : IEnumerable<string>

并将GetEnumerator替换为:

public IEnumerator<string> GetEnumerator()
{
  return issues.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
  return GetEnumerator();
}

脚本将失败并出现错误:

Object Doesn't Support this Property or Method

我的理解是 public GetEnumerator() 没有导出,因为它 是一个泛型方法, IEnumerable.GetEnumerator 不导出,因为 我的实例必须首先转换为 IEnumerable 但在 VBScript 中不能 投射物体。

这是真的吗? 是否可以告诉编译器 IEnumerable.GetEnumerator 应该是 导出为 public IEnumerable GetEnumerator? (或者这个声明没有 感觉?等等)

切换显式实现哪个接口,如:

IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
    // ...
}

public IEnumerator GetEnumerator()
{
    // ...
}

这是因为 IEnumerable.GetEnumerator has the DispId(-4) attribute,这是 VBScript 通过 IDispatch.Invoke 使用的内容。

泛型方法和具有泛型类型的方法在 COM 中不可见,因此如果您不想更改代码,请为 COM 定义一个额外的方法:

// Test if the .NET framework dispatches the method if you apply the following attribute
//[ComVisible(false)]
[DispId(-4)]
public IEnumerator NewEnum()
{
    return ((IEnumerable)this).GetEnumerator();
}