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?
source to share
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.
source to share