编组一个ComVisible组件vararg数组参数

时间:2016-11-01 10:32:40

标签: c# vb6 com-interop vb6-migration

我正在考虑将用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);

...我得到SAFEARRAY(VARIANT)*,但没有vararg。但是,如果我声明为

Recordset ExecSPReturnRS(string storedProc, params object[] arguments);

...然后我得到vararg但是SAFEARRAY没有被引用声明。

我希望MarshalAsAttribute可能是要走的路,但到目前为止我能想出的最好的是:

Recordset ExecSPReturnRS(string storedProc, 
                         [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
                         object[] arguments);

但这给了我相同的MIDL,好像我在没有MarshalAs的情况下声明为params

从本质上讲,我希望MIDL反映出我同时指定了refparams,这在C#下是非法的。我错过了什么咒语?

<小时/> 编辑:似乎最终目标是什么令人困惑。本质上,我们有一个由许多传统VB6组件组成的应用程序。为了消除遗留债务,我们需要能够将VB组件逐位移动到.NET。在该组件依赖于其他组件的情况下,.NET需要与现有的VB6和经典ASP一起使用,理想情况下不需要更改代码。一些遗留组件将被完全重构,最终没有COM依赖。许多VB6组件都使用早期绑定。

目前,当我使用.NET中的param声明代替VB6 ParamArray时,针对该对象构建VB6组件会导致函数或接口标记为受限制,或者该函数使用VB中的Visual Basic 错误中不支持的自动化类型。如果我使用ref代替,我会收到构建错误类型不匹配:数组或用户定义的预期类型。

在VB6中调用我正在查看的特定组件:

Set rs = dbconn.ExecSPReturnRS("dbo.StoredProc", _
    Array("@param1", value), _ 
    Array("@param2", value))

我认为这个问题是一个类型库问题,因为我的理解是VB将在构建时使用它来在早期绑定时验证调用。但是我已经发现,如果我迟到绑定所有内容,那么VB构建成功并且调用似乎有效。然而,这将需要遗留VB6的源代码更改,而不是在后期绑定时丢失自动完成,我预计我也会失去参数的构建时验证。但它可能是我们最好的选择。

最后一点说明:目前这是研究/ PoC,以找出需要什么和不需要什么。最终,旨在成为所有对象的逐行转换。某些对象需要公开COM接口,其他对象则不需要,其他对象将被重构或删除。但是,为了向后兼容,我们需要维持COM兼容接口,至少在短期到中期的同时进行迁移。

1 个答案:

答案 0 :(得分:0)

使用类型库导入器(Tlbimp.exe)生成互操作程序集,然后使用Redgate Reflector或类似工具反编译生成的程序集。 Reflector(至少)将生成正确地装饰有必要互操作属性的接口,并且可以将代码复制并粘贴到您自己的源文件中。