[英]VB6 Variant Type to .NET Type
I have some VB6 code that can't be modified easily that looks like this: 我有一些无法轻易修改的VB6代码,如下所示:
Dim cCount as Long
Dim rCount as Long
Dim result()
Set mx = CreateObject("Component.Class")
Dim rtn = mx.GetList(rCount,cCount,result)
The method it calls is currently a VB6 component that we've migrated to .NET with one issue. 它调用的方法目前是一个VB6组件,我们已经迁移到.NET,只有一个问题。 We're not sure what type the result() is looking for since it's a variant type.
我们不确定result()正在寻找什么类型,因为它是变体类型。 We've tried object, object[], object[][], string, string[], etc, none of which have worked.
我们已经尝试过object,object [],object [] [],string,string []等,其中没有一个有效。
Here's an example: 这是一个例子:
public bool GetList(ref long rCount, ref long cCount, ref object result)
{
...
}
I've even tried setting the third param to VariantWrapper since it will add ByRef as necessary: 我甚至尝试将第三个参数设置为VariantWrapper,因为它会根据需要添加ByRef:
public bool GetList(ref long rCount, ref long cCount, VariantWrapper result)
{
...
}
Any ideas what I can set the incoming result to be so that I don't have an unhandled exception? 我可以设置传入结果的任何想法,以便我没有未处理的异常?
I've created a test Interface (for COM), test Class, and test VB6 app to ensure it was an issue with the Variant. 我已经创建了一个测试接口(用于COM),测试类和测试VB6应用程序,以确保它是Variant的一个问题。 So, it's defined like so:
所以,它的定义如下:
.NET Interface: .NET接口:
[DispId(1)]
[ComVisible(true)]
string Test(ref object[] value);
VB 6 method: VB 6方法:
Private Sub Command1_Click()
Set mx = CreateObject("Component.Class")
Dim result()
MsgBox mx.Test(result)
End Sub
Same issue as described above. 与上述相同的问题。 In VB6, it just throws me out.
在VB6中,它只是抛弃了我。 If I compile and run it, I get a generic .NET exception and it throws me out.
如果我编译并运行它,我会得到一个通用的.NET异常,它会抛弃我。
Your C# declaration is wrong. 您的C#声明是错误的。 A VB6 "Long" is 32-bits for historical reasons.
由于历史原因,VB6“Long”是32位。 That's an int on the C# side.
这是C#方面的一个int。 With the stack frame wrong, you have no odds of getting the "result" argument passed correctly.
如果堆栈帧错误,则无法正确传递“result”参数。
It ought to be a SafeArray of Variants, object[] in C#. 它应该是一个变量的SafeArray,C#中的object []。
Put a breakpoint on the mx.GetList(rCount,cCount,result)
line. 在
mx.GetList(rCount,cCount,result)
行上放置一个断点。 Once hit, add a "quick watch" expression of mx.GetList(rCount,cCount,result)
. 点击后,添加
mx.GetList(rCount,cCount,result)
的“快速监视”表达式。 The toolwindow should show you what the resulting runtime-type is. 工具窗口应该显示生成的运行时类型是什么。 Most likely it is a "comresult" and will not provide much information, but it may provide a hint to the return type.
最有可能的是它是“comresult”并且不会提供太多信息,但它可能提供返回类型的提示。
I think the ref
keyword may be causing some trouble here. 我认为
ref
关键字可能会在这里造成一些麻烦。 The types have to match exactly for that to work. 类型必须完全匹配才能工作。
However, if your method simply accepts a reference to any object
by value , (instead of by ref
), it can get passed anything, since everything derives from object
in .NET. 但是,如果你的方法只是通过值接受对任何
object
的引用(而不是ref
),它可以传递任何东西,因为所有东西都是从.NET中的object
派生的。
How well this translates to VB6/COM interop, I don't know. 我不知道这对于VB6 / COM互操作有多好。 But it seems that this is at least worth a shot:
但似乎这至少值得一试:
C# code : C#代码 :
public string GetTypeName(object value)
{
return value.GetType().FullName;
}
VB6 code : VB6代码 :
Set mx = CreateObject("Component.Class")
Dim result()
MsgBox mx.GetTypeName(result)
Does that give you anything? 这会给你什么吗?
Here's an idea. 这是一个想法。 I could be dead wrong here -- I've not much experience in migrating VB6 apps to .NET -- but it seems to me that if you can get as far as (the C# equivalent of) this line...
我在这里可能是错误的 - 我没有太多将VB6应用程序迁移到.NET的经验 - 但在我看来,如果你可以达到(C#相当于)这一行......
Set mx = CreateObject("Component.Class")
...then you're golden. ......那你就是金色的。 You can use reflection to figure out what parameters the
GetList
method wants. 您可以使用反射来确定
GetList
方法想要的参数。
First get the System.Type
object representing the type of mx
: 首先获取表示
mx
类型的System.Type
对象:
Type mxType = mx.GetType();
Then find the GetList
method(s) for that type: 然后找到该类型的
GetList
方法:
MethodInfo[] getListMethods = mxType.GetMember("GetList")
.OfType<MethodInfo>()
.Where(m => m.GetParameters().Length == 3)
.ToArray();
This will give you a MethodInfo[]
array of all the public overloads of GetList
taking 3 parameters. 这将为您提供一个
MethodInfo[]
数组,其中GetList
3个参数的GetList
的所有公共重载。 From here the possible types of result
will be: 从这里可能的
result
类型将是:
Type[] possibleResultTypes = getListMethods
.Select(m => m.GetParameters()[2].ParameterType)
.ToArray();
I know only how it's used in .Net where you pass a reference to a Variant
like this: 我只知道在.Net中如何使用它来传递对
Variant
的引用,如下所示:
int port = 2;
object pvPort = new System.Runtime.InteropServices.VariantWrapper(port);
gimp.SetPort(ref pvPort);
After this, put a breakpoint and check the variant type if you're not sure about it. 在此之后,如果您不确定,请设置断点并检查变体类型。
The main thing is using VariantWrapper
so the dll understands. 主要的是使用
VariantWrapper
所以dll理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.