IEnumerable 在 COM 中可见,但 ICollection 不可见?
IEnumerable is visible in COM, but not ICollection?
我的 main class 中有一堆 Dictionary(Of Integer, SomeClass),我使用 AutoDual 供 COM 使用。用户需要遍历 VBA 中的实例(特别是 Excel),所以我在主 class...
中有一堆这样的实例
Public ReadOnly Property Inflations() As IEnumerable
Get
Return InflationsDict.Values
End Get
End Property
我可以像这样在我的 VBA 代码中使用它...
For Each I In CP.Inflations...
但这不支持计数。字典也公开了 ICollection,它有 .Count,但是当我做这个单一的改变时...
Public ReadOnly Property Inflations() As ICollection
该方法从 COM 中消失,相同的 For Each 得到 "Run-time error 438 Object doesn't support this property or method." 它在 VB.net 中继续正常工作。
有人告诉我基本规则是非泛型应该可以导出。编译过程中什么也没有出现 - 而当我尝试在云雀上导出 IEnumerable(Of Inflation)
时,输出中肯定会出现警告。
适用于这种情况的规则是否有边栏?
我可以看出我发布了一些误导性评论。您 运行 遇到的问题是 ICollection 成员将被公开,但它的继承接口 (IEnumerable) 不会。这打破了迭代集合的能力。
让我们为字典编写一个接口。我会假设变体:
<ComVisible(True)> _
<InterfaceType(ComInterfaceType.InterfaceIsDual)> _
Public Interface IMyDictionary
ReadOnly Property Count As Integer
Function Contains(ByVal key As Object) As Boolean
<DispId(0)> Property Item(ByVal key As Object) As Object
<DispId(-4)> Function GetEnumerator() As System.Collections.IEnumerator
End Interface
带有示例实现:
<ComVisible(True)> _
<ClassInterface(ClassInterfaceType.None)> _
<ProgId("Whosebug.Example")> _
Public Class Example
Implements IMyDictionary
Private collection As New Dictionary(Of Integer, String)
Public Sub New()
collection = New Dictionary(Of Integer, String)
'' Add some sample data
collection.Add(1, "one")
collection.Add(2, "two")
collection.Add(3, "three")
End Sub
Public ReadOnly Property Count As Integer Implements IMyDictionary.Count
Get
Return collection.Count
End Get
End Property
Public Function GetEnumerator() As IEnumerator Implements IMyDictionary.GetEnumerator
Return CType(collection.Values, System.Collections.IEnumerable).GetEnumerator()
End Function
Public Property Item(ByVal key As Object) As Object Implements IMyDictionary.Item
Get
Return collection(CInt(key))
End Get
Set(ByVal value As Object)
collection(CInt(key)) = CStr(value)
End Set
End Property
Public Function Contains(key As Object) As Boolean Implements IMyDictionary.Contains
Return collection.ContainsKey(CInt(key))
End Function
End Class
练习它的示例 VBScript:
Set obj = CreateObject("Whosebug.Example")
WScript.Echo "Count=" & obj.Count
WScript.Echo "Value for key 2=" & obj(2)
WScript.Echo "Contains(3)=" & obj.Contains(3)
WScript.Echo "Contains(42)=" & obj.Contains(42)
WScript.Echo "Values:"
For Each elem in obj
WScript.Echo " " & elem
Next
输出:
Count=3
Value for key 2=two
Contains(3)=True
Contains(42)=False
Values:
one
two
three
我的 main class 中有一堆 Dictionary(Of Integer, SomeClass),我使用 AutoDual 供 COM 使用。用户需要遍历 VBA 中的实例(特别是 Excel),所以我在主 class...
中有一堆这样的实例Public ReadOnly Property Inflations() As IEnumerable
Get
Return InflationsDict.Values
End Get
End Property
我可以像这样在我的 VBA 代码中使用它...
For Each I In CP.Inflations...
但这不支持计数。字典也公开了 ICollection,它有 .Count,但是当我做这个单一的改变时...
Public ReadOnly Property Inflations() As ICollection
该方法从 COM 中消失,相同的 For Each 得到 "Run-time error 438 Object doesn't support this property or method." 它在 VB.net 中继续正常工作。
有人告诉我基本规则是非泛型应该可以导出。编译过程中什么也没有出现 - 而当我尝试在云雀上导出 IEnumerable(Of Inflation)
时,输出中肯定会出现警告。
适用于这种情况的规则是否有边栏?
我可以看出我发布了一些误导性评论。您 运行 遇到的问题是 ICollection 成员将被公开,但它的继承接口 (IEnumerable) 不会。这打破了迭代集合的能力。
让我们为字典编写一个接口。我会假设变体:
<ComVisible(True)> _
<InterfaceType(ComInterfaceType.InterfaceIsDual)> _
Public Interface IMyDictionary
ReadOnly Property Count As Integer
Function Contains(ByVal key As Object) As Boolean
<DispId(0)> Property Item(ByVal key As Object) As Object
<DispId(-4)> Function GetEnumerator() As System.Collections.IEnumerator
End Interface
带有示例实现:
<ComVisible(True)> _
<ClassInterface(ClassInterfaceType.None)> _
<ProgId("Whosebug.Example")> _
Public Class Example
Implements IMyDictionary
Private collection As New Dictionary(Of Integer, String)
Public Sub New()
collection = New Dictionary(Of Integer, String)
'' Add some sample data
collection.Add(1, "one")
collection.Add(2, "two")
collection.Add(3, "three")
End Sub
Public ReadOnly Property Count As Integer Implements IMyDictionary.Count
Get
Return collection.Count
End Get
End Property
Public Function GetEnumerator() As IEnumerator Implements IMyDictionary.GetEnumerator
Return CType(collection.Values, System.Collections.IEnumerable).GetEnumerator()
End Function
Public Property Item(ByVal key As Object) As Object Implements IMyDictionary.Item
Get
Return collection(CInt(key))
End Get
Set(ByVal value As Object)
collection(CInt(key)) = CStr(value)
End Set
End Property
Public Function Contains(key As Object) As Boolean Implements IMyDictionary.Contains
Return collection.ContainsKey(CInt(key))
End Function
End Class
练习它的示例 VBScript:
Set obj = CreateObject("Whosebug.Example")
WScript.Echo "Count=" & obj.Count
WScript.Echo "Value for key 2=" & obj(2)
WScript.Echo "Contains(3)=" & obj.Contains(3)
WScript.Echo "Contains(42)=" & obj.Contains(42)
WScript.Echo "Values:"
For Each elem in obj
WScript.Echo " " & elem
Next
输出:
Count=3
Value for key 2=two
Contains(3)=True
Contains(42)=False
Values:
one
two
three