C # to VB6 interop: indexed array properties not available for nested COM interfaces

I would like to publish a C # class library via COM interop so that it can be used by VB6 clients. For demonstration purposes, consider the following snippet:

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; }
    }
}

      

After registering the library in the system, the COM interface can be used in VB6. However, accessing an indexed value array property doesn't work:

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

      

The only thing I found was to create a temporary array variable. This allows me to access the indexed interface correctly:

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

      

Unfortunately, the array I illustrated here is a simple oversimplification. In real life, I need to access COM interfaces that are deep inside nested array structures. For example, the following class structure ...

Class1
    Class2[]
        Class3[]
            Class4[]

      

... will eventually force me to create three temporary array variables before I can actually access an instance of class 4.

Is this a VB6 limitation? If so, is there a way to access the nested array interfaces without cluttering the code with temporary variables?

+3


source to share


1 answer


I retired VB6 a long time ago and can't test it anymore. But it almost certainly suffers from syntactic ambiguity. Did you mean to index a property or the return value of a property? You like the latter interpretation, but that's not what it does. You need to write something like this:

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

      

or

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

      

Don't know if this can compile. Blech anyway.




You need to progress by actually naming the indexed property. Like this:

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; }
    }
}

      

Note that this also makes it much less painful for the VB6 code to iterate over the array. You are not creating a new array over and over. VB6 code gets short and sweet:

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

      

If you really need to return or assign a complete array, you should use the.

+3


source







All Articles