我正在考虑将一些用VB6编写的遗留COM代码迁移到.NET,但是这需要生成一个与原始代码相当接近的类型表。
在早期绑定到其他VB6组件时,我遇到了传递参数数组的问题。在原始VB6中,签名如下所示:
Public Function ExecSPReturnRS(ByVal strProcAs String, _
ParamArray varParams() As Variant) As Recordset生成的MIDL如下所示:
[id(0x60030009), vararg]
HRESULT ExecSPReturnRS([in] BSTR strProc,
[in, out] SAFEARRAY(VARIANT)* varParams,
[out, retval] _Recordset** );使用C#,我无法确定生成相同MIDL的正确声明。我要么遗漏了vararg声明,要么varParams参数被声明为SAFEARRAY(VARIANT)而不是SAFEARRAY(VARIANT)*。
因此,如果在C#中,我声明为:
Recordset ExecSPReturnRS(string storedProc, ref object[] arguments);...I得到SAFEARRAY(VARIANT)*,但没有vararg。但是如果我声明为
Recordset ExecSPReturnRS(string storedProc, params object[] arguments);...then I得到vararg,但SAFEARRAY不是通过引用声明的。
我希望MarshalAsAttribute可能是前进的道路,但到目前为止,我能想到的最好的方法是:
Recordset ExecSPReturnRS(string storedProc,
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
object[] arguments);但这给了我同样的MIDL,就像我在没有元帅的情况下宣布为params一样。
本质上,我希望MIDL能够反映出我已经指定了ref和params,这在C#下是非法的。我错过了什么咒语?
编辑:,似乎对最终目标有一些混淆。本质上,我们有一个由许多遗留VB6组件组成的应用程序。为了消除遗留的债务,我们需要能够一点一点地将VB组件移到.NET上。如果该组件依赖于其他组件,则.NET需要与现有的VB6和经典ASP一起使用,理想情况下不需要更改代码。一些遗留组件将被完全重构,并最终不依赖COM。许多VB6组件使用早期绑定。
目前,当我使用.NET中的.NET声明代替VB6 ParamArray时,针对该对象构建VB6组件会产生标记为受限的函数或接口,或者该函数使用VB中Visual错误中不支持的自动化类型。如果我使用ref,就会得到预期的生成错误类型不匹配:数组或用户定义的类型。
在VB6中对特定组件的调用如下所示:
Set rs = dbconn.ExecSPReturnRS("dbo.StoredProc", _
Array("@param1", value), _
Array("@param2", value))我认为这个问题是一个类型化的问题,因为我的理解是VB将在构建时使用它来验证早期绑定时的调用。然而,我发现,如果我延迟绑定所有的东西,那么VB构建就会成功,并且调用似乎可以工作。然而,这将需要对遗留VB6进行源代码更改,并且除了在后期绑定时丢失自动完成之外,我还希望我还会丢失参数的构建时验证。但这可能是我们最好的选择。
最后一个注意事项:目前,这是一个研究/PoC,以找出什么是必需的,什么是不需要的。最终,这是而不是,它打算对所有对象进行逐行转换。有些对象需要公开COM接口,另一些则不需要公开,而另一些对象则需要重构或删除。然而,我们需要一些地方来支持COM兼容接口,以实现向后兼容性,至少在迁移过程中,短期到中期是如此。
发布于 2019-05-14 20:20:14
使用类型库导入器(Tlbimp.exe)生成互操作程序集,然后使用Reflector或类似工具解压缩生成的程序集。反射器(至少)将生成具有必要的互操作属性的接口,并且代码可以复制并粘贴到您自己的源文件中。
https://stackoverflow.com/questions/40358296
复制相似问题