使用显式接口实现时,如何选择导出到COM的成员
本文关键字:COM 成员 选择 显式接口实现 何选择 | 更新日期: 2023-09-27 18:17:56
如果我的类实现IEnumerable
,我可以使用VBScript的For Each
循环:
[ComVisible(true)]
[ProgId("Stackoverflow.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("Stackoverflow.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();
}
脚本将失败并出现错误:
对象不支持此属性或方法
我的理解是,公共GetEnumerator()
不被导出,因为它是一个通用方法,IEnumerable.GetEnumerator
不导出,因为我的实例必须首先转换为IEnumerable
,但在VBScript不能把对象。
这是真的吗?是否有可能告诉编译器IEnumerable.GetEnumerator
应该是导出为public IEnumerable GetEnumerator
?(或者这句话是否定的理解吗?等)
切换显式实现的接口,例如:
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
// ...
}
public IEnumerator GetEnumerator()
{
// ...
}
这是因为IEnumerable.GetEnumerator
具有DispId(-4)
属性,这是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();
}