我有一些COM库需要从WF4活动访问,所以我使用tlbimp
为它们生成托管包装。这很好,但在一些情况下,有一个COM方法需要一个变量数组作为其参数之一,而数组的其中一个元素是来自另一个DLL的COM类的一个实例,即使我有一个引用表示同一个对象的托管包装的引用,也不会看到如何获取引用。如何访问使用TLBIMP创建的托管.NET对象的底层COM对象
举个例子,说我有两个叫ABC
和DEF
COM库,为此,我创建了托管的包装使用tlbimp
称为ABCManaged
和DEFManaged
。说DEF
具有以下签名的方法(原谅VB风格的签名,这是它在文档中的方式):它被作为DEFManaged
表示如下
CallFunction (parmArray() as Variant) as Long
:
int CallFunction(ref object parmArray)
到现在为止还挺好。现在,作为CallFunction()
参数的变量数组的元素是不同类型的,所以在我的情况下,第一个元素是double
,第二个元素是ABC
的实例。下面是我如何建立我的数组传递给我的管理CallFunction()
:
// obtain our managed ABC from the workflow context
ABCManaged abc = context.GetValue(this.InputABC);
object[] parameters = new object[2];
parameters[0] = new double();
parameters[1] = abc;
DEFManaged def = new DEFManaged();
def.CallFunction(parameters);
编译没有问题,但不工作 - 调用CallFunction()
抛出此异常:
System.ArgumentException: Value does not fall within the expected range.
我的猜测是, def
未正确收集到底层的非托管DEF
类型,可能是因为签名只有一个object
的数组,并且确定数组元素的实际类型的逻辑是在COM方法的实现中的某处CallFunction()
。我无法弄清楚如何将我的def
对象手动编组到非托管DEF
类型,然后将其粘贴到阵列中以传递到我的托管CallFunction()
。
使用直P/Invoke在这里也不是一个选项;我当然可以编写代码,但其中一个要求是WF4活动的用户能够访问DEFManaged
对象上的属性和方法,因此他们需要被管理的对象。
该对象似乎正确地编组到com服务器。否则会引发另一个异常,很可能是一个'InvalidComObjectException'或另一个'COMException'。服务器实现抛出'ArgumentException' get。 http://msdn.microsoft.com/en-us/library/9ztbc5s1.aspx – Carsten 2013-02-28 08:05:56
好吧,'object []'正在编组到'Variant()',但我的猜测是数组中的实际元素是因为接口不知道它必须这样做,所以没有正确编组,因为COM对象和它的管理对象的签名都没有指定数组元素的类型。 你是否认为这个猜测是错误的,并且我的数组的第二个元素(在我的例子中是一个'ManagedABC'对象)被正确封送到底层COM对象(在我的例子中是一个'DEF'对象),尽管有接口没有指定该类型? – user533676 2013-02-28 14:27:06
我误解了这里发生的事情:数组中的单个对象正在编组,但数组本身是通过值而不是通过引用传递的(COM对象要求它通过引用传递)。请参阅下面的答案,详细了解如何解决此问题。 – user533676 2013-03-16 14:17:56