封送ComVisible组件变量数组参数

本文关键字:数组 参数 变量 组件 ComVisible 封送 | 更新日期: 2023-09-27 18:15:42

我正在考虑将一些用VB6编写的遗留COM代码迁移到。net,但是这需要生成一个非常接近原始的typelib。

当早期绑定到其他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,如果我声明为params没有MarshalAs。

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


编辑:似乎有一些混乱的最终目标是什么。本质上,我们有一个由许多遗留的VB6组件组成的应用程序。为了消除遗留债务,我们需要能够一点一点地将VB组件转移到。net。当组件依赖于其他组件时,. net需要与现有的VB6和经典ASP兼容,理想情况下不需要修改代码。一些遗留组件将被完全重构,最终不再依赖于COM。许多VB6组件使用早期绑定。

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

在VB6中对我正在查看的特定组件的调用看起来像这样:

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

我认为这个问题是一个类型问题,因为我的理解是VB将在构建时使用它来验证早期绑定时的调用。然而,我后来发现,如果我晚绑定所有东西,那么VB构建是成功的,调用似乎可以工作。然而,这将需要更改遗留VB6的源代码,并且除了在后期绑定时失去自动完成功能外,我预计还会失去参数的构建时验证。但这可能是我们最好的选择。

最后一点:目前这是研究/PoC,以找出什么是需要的,什么是不需要的。最终,这是而不是,目的是对所有对象进行逐行转换。有些对象需要公开COM接口,有些对象则不需要,还有一些对象将被重构或删除。然而,在某些地方,我们将需要维持一个向后兼容的COM兼容接口,至少在迁移进行的中短期内是这样。

封送ComVisible组件变量数组参数

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