Chr*_*s J 5 c# vb6 com-interop vb6-migration
我正在考虑将一些用 VB6 编写的遗留 COM 代码迁移到 .NET,但这需要生成一个与原始代码相当接近的类型库。
在早期绑定到其他 VB6 组件时,我遇到了传递参数数组的问题。在最初的 VB6 中,签名如下所示:
Public Function ExecSPReturnRS(ByVal strProcAs String, _
ParamArray varParams() As Variant) As Recordset
Run Code Online (Sandbox Code Playgroud)
并生成如下所示的 MIDL:
[id(0x60030009), vararg]
HRESULT ExecSPReturnRS([in] BSTR strProc,
[in, out] SAFEARRAY(VARIANT)* varParams,
[out, retval] _Recordset** );
Run Code Online (Sandbox Code Playgroud)
使用 C#,我无法确定生成相同 MIDL 的正确声明。我要么缺少vararg声明,要么 varParams 参数被声明为而SAFEARRAY(VARIANT)不是SAFEARRAY(VARIANT)*.
因此,如果在 C# 中我声明为:
Recordset ExecSPReturnRS(string storedProc, ref object[] arguments);
Run Code Online (Sandbox Code Playgroud)
...我明白了SAFEARRAY(VARIANT)*,但没有vararg。但是如果我声明为
Recordset ExecSPReturnRS(string storedProc, params object[] arguments);
Run Code Online (Sandbox Code Playgroud)
...然后我得到了vararg但 SAFEARRAY 未声明为引用。
我希望这MarshalAsAttribute可能是可行的方法,但到目前为止我能想到的最好方法是:
Recordset ExecSPReturnRS(string storedProc,
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
object[] arguments);
Run Code Online (Sandbox Code Playgroud)
但这给了我相同的 MIDL,就好像我声明params没有元帅一样。
本质上,我希望 MIDL 反映出来,就好像我同时指定了ref和params,这在 C# 下是非法的。我缺少什么咒语?
就目前而言,当我使用param.NET 中的声明来代替 VB6 ParamArray 时,针对该对象构建 VB6 组件会导致函数或接口标记为受限,或者该函数使用 VB6 中不支持的自动化类型。 VB 中的Visual Basic错误。如果我改用ref它,则会收到构建错误“类型不匹配:需要数组或用户定义的类型”。
在 VB6 中对我正在查看的特定组件的调用类似于:
Set rs = dbconn.ExecSPReturnRS("dbo.StoredProc", _
Array("@param1", value), _
Array("@param2", value))
Run Code Online (Sandbox Code Playgroud)
我假设这个问题是 typelib 问题,因为我的理解是 VB 将在构建时使用它来验证早期绑定时的调用。然而我后来发现,如果我晚绑定所有内容,那么 VB 构建就会成功并且调用似乎可以工作。然而,这将需要更改旧版 VB6 的源代码,并且除了后期绑定时失去自动完成功能之外,我预计还会失去参数的构建时验证。但这可能是我们最好的选择。
最后一点:目前这是一项研究/PoC,旨在找出需要什么和不需要什么。最终,这并不是要对所有对象进行逐行转换。某些对象需要公开 COM 接口,其他对象则不需要,还有一些对象将被重构或删除。然而,在某些地方,我们需要维持 COM 兼容接口以实现向后兼容性,至少在迁移过程中的中短期内如此。
使用类型库导入器 (Tlbimp.exe) 生成互操作程序集,然后使用 Redgate Reflector 或类似工具反编译生成的程序集。Reflector(至少)将生成用其必需的互操作属性正确修饰的接口,并且可以将代码复制并粘贴到您自己的源文件中。
| 归档时间: |
|
| 查看次数: |
426 次 |
| 最近记录: |