我有一些无法轻易修改的VB6代码,如下所示:
Dim cCount as Long
Dim rCount as Long
Dim result()
Set mx = CreateObject("Component.Class")
Dim rtn = mx.GetList(rCount,cCount,result)
它调用的方法当前是一个VB6组件,我们已经迁移到.NET,只有一个问题。我们不确定result()正在寻找什么类型,因为它是变体类型。我们尝试过object,object [],object [] [],string,string []等,但都没有。
以下是一个例子:
public bool GetList(ref long rCount, ref long cCount, ref object result)
{
...
}
我甚至尝试将第三个参数设置为VariantWrapper,因为它会根据需要添加ByRef:
public bool GetList(ref long rCount, ref long cCount, VariantWrapper result)
{
...
}
我可以设置传入结果的任何想法,以便我没有未处理的异常吗?
我已经创建了一个测试接口(用于COM),测试类和测试VB6应用程序,以确保它是Variant的一个问题。所以,它的定义如下:
.NET接口:
[DispId(1)]
[ComVisible(true)]
string Test(ref object[] value);
VB 6方法:
Private Sub Command1_Click()
Set mx = CreateObject("Component.Class")
Dim result()
MsgBox mx.Test(result)
End Sub
与上述相同的问题。在VB6中,它只是抛弃了我。如果我编译并运行它,我会得到一个通用的.NET异常,它会把我抛弃。
答案 0 :(得分:4)
你的C#声明是错误的。由于历史原因,VB6“Long”是32位。这是C#方面的一个int。如果堆栈帧错误,则无法正确传递“result”参数。
它应该是变量的SafeArray,C#中的object []。
答案 1 :(得分:1)
在mx.GetList(rCount,cCount,result)
行放置一个断点。点击后,添加mx.GetList(rCount,cCount,result)
的“快速观看”表达式。工具窗口应该显示生成的运行时类型是什么。很可能它是一个“comresult”并且不会提供太多信息,但它可能会提供返回类型的提示。
答案 2 :(得分:1)
我认为ref
关键字可能会在这里造成一些麻烦。这些类型必须完全匹配才能发挥作用。
但是,如果您的方法仅接受对值的任何object
的引用(而不是ref
),则可以传递任何内容,因为所有内容都来自.NET中的object
。
这个转换为VB6 / COM互操作的程度,我不知道。但似乎这至少值得一试:
C#代码:
public string GetTypeName(object value)
{
return value.GetType().FullName;
}
VB6代码:
Set mx = CreateObject("Component.Class")
Dim result()
MsgBox mx.GetTypeName(result)
这会给你什么吗?
这是一个想法。我在这里可能会出错 - 我在将VB6应用程序迁移到.NET方面没有多少经验 - 但在我看来,如果你能够达到(C#相当于)这一行......
Set mx = CreateObject("Component.Class")
......那你就是金色的。您可以使用反射来确定GetList
方法想要的参数。
首先获取表示System.Type
类型的mx
对象:
Type mxType = mx.GetType();
然后找到该类型的GetList
方法:
MethodInfo[] getListMethods = mxType.GetMember("GetList")
.OfType<MethodInfo>()
.Where(m => m.GetParameters().Length == 3)
.ToArray();
这将为您提供MethodInfo[]
数组,其中包含3个参数的GetList
的所有公共重载。从这里result
的可能类型将是:
Type[] possibleResultTypes = getListMethods
.Select(m => m.GetParameters()[2].ParameterType)
.ToArray();
答案 3 :(得分:0)
我只知道在.Net中如何使用它来传递对Variant
的引用,如下所示:
int port = 2;
object pvPort = new System.Runtime.InteropServices.VariantWrapper(port);
gimp.SetPort(ref pvPort);
在此之后,如果您不确定,请设置断点并检查变体类型。
主要是使用VariantWrapper
所以dll理解。