Suppose I have a native COM class A which implements an interface ITest,
and a native COM class B which features a member function taking a
parameter of type ITest. With normal COM Interop, I can call this
function in C# by explicitely casting to ITest as in
someB.TestFunction((ITest) someA);
which also take care of the QueryInterface behind the scenes.
Suppose further that for some obscure reason a user wants to
use the library in a late-bound scenario using reflection.
I can load the assembly, locate types "typeA", "typeB",
"typeITest", and dynamically create instances of A and B
storing them in object variables "objA" and "objB".
But I don't know how to pass objA as an argument when
invoking the TestFunction on objB:
typeB.InvokeMember("TestFunction",
BindingFlags.InvokeMethod,
null,
objB,
new object[] {objA}); // ???
With the above code, the function complains that the argument
is not of type ITest. I tried something along the lines of
Guid guidITest = typeITest.GUID;
IntPtr pUnk = Marshal.GetIUnknownForObject(objA);
IntPtr pITest;
int HRESULT = Marshal.QueryInterface(pUnk,ref guidITest,out pITest);
object objITest = Marshal.GetTypedObjectForIUnknown(pUnk, typeITest);
but I invariably end up with some object instance of type A (AClass),
although it looks like the QueryInterface returns meaningful pointers.
Any insights appreciated.
Christian Fröschlin - 19 Feb 2007 14:36 GMT
> Guid guidITest = typeITest.GUID;
> IntPtr pUnk = Marshal.GetIUnknownForObject(objA);
> IntPtr pITest;
> int HRESULT = Marshal.QueryInterface(pUnk,ref guidITest,out pITest);
> object objITest = Marshal.GetTypedObjectForIUnknown(pUnk, typeITest);
I should note that of course the result of QueryInterface is ignored
here anyway, it was just for testing. I didn't find a method in Marshal
to get an Object from the pointer except GetTypedObjectForIUnknown,
so I used the pUnk (using pITest didn't work either).
Christian Fröschlin - 20 Feb 2007 09:20 GMT
> With the above code, the function complains that the argument
> is not of type ITest.
After some further research, it all seems to boil down to COM
not supporting late binding for non-default interfaces. Some
links to further information for anyone interested:
http://www.microsoft.com/mind/0100/Basics/Basics0100.asp
http://www.thescripts.com/forum/thread241528.html
http://www.devarticles.com/c/a/C-Sharp/Using-Late-Bound-COM-Objects/3/