IEnumerable在COM中可见,但不是ICollection?

时间:2015-06-05 18:35:11

标签: .net vb.net com-interop

我的主类中有一堆Dictionary(Of Integer,SomeClass),我可以使用AutoDual进行COM使用。用户需要迭代VBA中的实例(特别是Excel),所以我在我的主类中有一堆这些...

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得到“运行时错误438对象不支持此属性或方法”。它继续在VB.net中正常工作。

我被告知基本规则是非泛型应该导出OK。在编译期间没有任何事情发生 - 而当我尝试在云雀上导出IEnumerable(Of Inflation)时,输出中肯定会出现警告。

在这种情况下,规则的侧边栏是否适用?

1 个答案:

答案 0 :(得分:1)

我可以说我发布了一些误导性评论。您遇到的问题是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("StackOverflow.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("StackOverflow.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