C# 到 VB6 互操作:无法跨嵌套 COM 接口访问索引数组属性
C# to VB6 interop: indexed array properties are not accessible across nested COM interfaces
我想通过 COM 互操作发布一个 C# class 库,以便 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 接口。例如,下面的 class 结构...
Class1
Class2[]
Class3[]
Class4[]
...最终会迫使我创建三个临时数组变量,然后才能实际访问 Class4 的实例。
这是VB6的限制吗?如果是这样,有没有什么方法可以访问嵌套数组接口而不用临时变量弄乱代码?
我很久以前就停用了 VB6,不能再检查了。但几乎可以肯定它存在语法歧义。您是要索引 属性 还是 属性 的 return 值?您喜欢后一种解释,但事实并非如此。你必须这样写:
str = (c1.m_Class2Instances)(0).m_sStr
或:
str = c1.m_Class2Instances()(0).m_sStr
不知道这是否可以编译。无论如何。
您需要通过实际编写索引 属性 来取得成功。像这样:
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 代码迭代数组。您不会一遍又一遍地创建新数组。 VB6 代码也变得简短而有趣:
Dim c1 As New cslib.Class1
Dim str = c1(0).m_sStr
如果你真的,真的需要return或分配一个完整的数组,那么你必须使用一个方法来代替。
我想通过 COM 互操作发布一个 C# class 库,以便 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 接口。例如,下面的 class 结构...
Class1
Class2[]
Class3[]
Class4[]
...最终会迫使我创建三个临时数组变量,然后才能实际访问 Class4 的实例。
这是VB6的限制吗?如果是这样,有没有什么方法可以访问嵌套数组接口而不用临时变量弄乱代码?
我很久以前就停用了 VB6,不能再检查了。但几乎可以肯定它存在语法歧义。您是要索引 属性 还是 属性 的 return 值?您喜欢后一种解释,但事实并非如此。你必须这样写:
str = (c1.m_Class2Instances)(0).m_sStr
或:
str = c1.m_Class2Instances()(0).m_sStr
不知道这是否可以编译。无论如何。
您需要通过实际编写索引 属性 来取得成功。像这样:
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 代码迭代数组。您不会一遍又一遍地创建新数组。 VB6 代码也变得简短而有趣:
Dim c1 As New cslib.Class1
Dim str = c1(0).m_sStr
如果你真的,真的需要return或分配一个完整的数组,那么你必须使用一个方法来代替。