How can I invoke a method of a private COM interface, defined in a base class, from a derived class?
For example, here is the COM interface, IComInterface
(IDL):
[
uuid(9AD16CCE-7588-486C-BC56-F3161FF92EF2),
oleautomation
]
interface IComInterface: IUnknown
{
HRESULT ComMethod([in] IUnknown* arg);
}
Here's the C# class BaseClass
from OldLibrary
assembly, which implements IComInterface
like this (note the interface is declared as private):
// Assembly "OldLibrary"
public static class OldLibrary
{
[ComImport(), Guid("9AD16CCE-7588-486C-BC56-F3161FF92EF2")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IComInterface
{
void ComMethod([In, MarshalAs(UnmanagedType.Interface)] object arg);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class BaseClass : IComInterface
{
void IComInterface.ComMethod(object arg)
{
Console.WriteLine("BaseClass.IComInterface.ComMethod");
}
}
}
Finally, here's an improved version, ImprovedClass
, which derives from BaseClass
, but declares and implement its own version of IComInterface
, because the base's OldLibrary.IComInterface
is inaccessible:
// Assembly "NewLibrary"
public static class NewLibrary
{
[ComImport(), Guid("9AD16CCE-7588-486C-BC56-F3161FF92EF2")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IComInterface
{
void ComMethod([In, MarshalAs(UnmanagedType.Interface)] object arg);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class ImprovedClass :
OldLibrary.BaseClass,
IComInterface,
ICustomQueryInterface
{
// IComInterface
void IComInterface.ComMethod(object arg)
{
Console.WriteLine("ImprovedClass.IComInterface.ComMethod");
// How do I call base.ComMethod here,
// otherwise than via reflection?
}
// ICustomQueryInterface
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
{
if (iid == typeof(IComInterface).GUID)
{
ppv = Marshal.GetComInterfaceForObject(this, typeof(IComInterface), CustomQueryInterfaceMode.Ignore);
return CustomQueryInterfaceResult.Handled;
}
ppv = IntPtr.Zero;
return CustomQueryInterfaceResult.NotHandled;
}
}
}
How do I call BaseClass.ComMethod
from ImprovedClass.ComMethod
without reflection?
I could use reflection, but in the real use case IComInterface
is a complex OLE interface with a number of members of complex signatures.
I thought that because both BaseClass.IComInterface
and ImprovedClass.IComInterface
are both COM interfaces with the same GUID and identical method signatures, and there's COM Type Equivalence in .NET 4.0+, so there has to be a way to do what I'm after without reflection.
Another requirement is that ImprovedClass
has to be derived from BaseClass
, because the C# client code expects an instance of BaseClass
, which it passes to the COM client code. Thus, containment of BaseClass
inside ImprovedClass
is not an option.
[EDITED] A real-life scenario which involves deriving from WebBrowser
and WebBrowserSite
is described here.
See Question&Answers more detail:
os