
Observation of idiosyncrasy when using Interfaces with both COM and .NET
Here is the basic premise.
Create, in a single typelib, two interfaces. Then a coclass which
inherits from one interface.
Like so:
[
object,
uuid(5EF870F3-96EA-44AA-AE81-A34378999923),
dual,
helpstring("ITestObjA Interface"),
pointer_default(unique)
]
interface ITestObjA : IDispatch
{
};
[
object,
uuid(05BA3174-D002-434a-BDC6-F7F8EC0AD80E),
dual,
helpstring("ITestObjB Interface"),
pointer_default(unique)
]
interface ITestObjB : IDispatch
{
[ id(1) ] HRESULT TestInt( [in] ITestNoIdData *pN, [in] ITestObjA
*pA );
};
[
uuid(B517FB75-0E6E-485A-B366-E672459D95E2),
helpstring("TestObjA Class")
]
coclass TestObjA
{
[default] interface ITestObjA;
};
Notice that in ITestObjB, the ITestNoIdData interface comes from a
different typelib, but that is irrelevant.
Now import this into a C# project by adding the dll as a reference.
What happens if I create a C# class implementing the ITestObjB
interface?
Well, the TestInt method will be forced to accept a TestObjA "class"
as the second parameter instead of the ITestObjA interface.
Now lets for experimental reasons add a second CoClass which inherits
from ITestObjA and import the reference again. This time the C#
environment and the RCW will be created with the correct TestInt
method signature for the second parameter which is ITestObjA. That
seems to work well on first inspection.
Let's create a third and then a fourth test. What if I create a
second dll with a coclass which implements ITestObjA. Then import
both dlls into the same C# project. Well, when I implement ITestObjB
in the C# environment, guess what, it still tries to list the second
parameter as the coclass and not the interface. This is very bad if I
want multiple coclasses in separate dlls implementing the same
interface.
Additionally, if I simply import this typelibrary into the C# project
and then create a C# class which inherits from ITestObjA, the
environment still lists the ITestObjB.TestInt method with the second
parameter as the TestObjA coclass. This is even worse.
The only solution to this seems to be to cut out the interfaces and
put them into a separate typelibrary.
What if I don't have access to the source code?
Some may say simply cut out the interfaces through OLE-View and make
your own typelibrary if you don't have the source code, but that is
not an option, as both the dll and the tlb would still have to be
referenced to get access to the coclass. This results in a duplicate
declaration issue.
Please advise.
-- Rob