C#到VB6互操作:嵌套的COM接口无法访问索引数组属性

时间:2015-08-05 18:52:07

标签: c# arrays com vb6 com-interop

我想通过COM interop发布一个C#类库,以便VB6客户端可以使用它。出于演示目的,请考虑以下代码段:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace cslib
{
    [ComVisible(true)]
    [Guid("...")]
    public interface IClass2
    {
        string m_sStr { get; set; }
    }

    [ComVisible(true)]
    [Guid("...")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Class2 : IClass2
    {
        public Class2()
        {
            m_sStr = "Hello";
        }

        public string m_sStr { get; set; }
    }

    [ComVisible(true)]
    [Guid("...")]
    public interface IClass1
    {
        Class2[] m_Class2Instances { get; set; }
    }

    [ComVisible(true)]
    [Guid("...")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Class1 : IClass1
    {
        public Class1()
        {
            List<Class2> lstClass2 = new List<Class2>();

            for (int i = 0; i < 5; i++)
                lstClass2.Add(new Class2());

            m_Class2Instances = lstClass2.ToArray();
        }

        public Class2[] m_Class2Instances { get; set; }
    }
}

在系统上注册库后,COM接口可在​​VB6中使用。但是,使用索引值访问数组属性似乎不起作用:

Dim c1 As New cslib.Class1
Dim str As String

'Error message = Wrong number of arguments or invalid property assignment
str = c1.m_Class2Instances(0).m_sStr

我发现的唯一替代方法是创建一个临时数组变量。这允许我正确访问索引接口:

Dim c1 As New cslib.Class1
Dim str As String

'Works, but requires detour via temp array
Dim arrc2() As cslib.Class2
arrc2 = c1.m_Class2Instances

str = arrc2(0).m_sStr

不幸的是,我在这里说明的阵列仅仅是简化。在现实生活中,我需要访问COM接口,这些接口位于嵌套数组结构的深处。例如,以下类结构......

Class1
    Class2[]
        Class3[]
            Class4[]

...最终会强制我创建三个临时数组变量,然后才能真正访问Class4的实例。

这是VB6的限制吗?如果是这样,有没有办法访问嵌套数组接口而不会使用临时变量混乱代码?

1 个答案:

答案 0 :(得分:3)

很久以前我已经退休了VB6,不能再检查这个了。但它几乎肯定会受到语法歧义的影响。您的意思是索引属性或属性的返回值吗?你喜欢后者的解释,但这不是它的作用。你必须写下这样的东西:

  str = (c1.m_Class2Instances)(0).m_sStr

或:

  str = c1.m_Class2Instances()(0).m_sStr

不知道这是否可以编译。 Bleh无论如何。

您需要通过实际编写索引属性来获得成功。像这样:

public interface IClass1 {
    Class2 this[int index] { get; set; }
}

public class Class1 : IClass1 {
    private List<Class2> lstClass2 = new List<Class2>();
    public Class1() {
        for (int i = 0; i < 5; i++) lstClass2.Add(new Class2());
    }

    public Class2 this[int index] {
        get { return lstClass2[index]; }
        set { lstClass2[index] = value; }
    }
}

请注意,如果让VB6代码迭代数组,这也会让 lot 减少痛苦。您不是一遍又一遍地创建新阵列。 VB6代码也变得简短和甜蜜:

Dim c1 As New cslib.Class1
Dim str = c1(0).m_sStr

如果你真的,真的需要返回或指定一个完整的数组,那么你必须使用一种方法。