I have written some C# code which returns a .NET object to unmanaged code as an IDispatch
pointer using Marshal.GetIDispatchForObject
, however, this object also implements other (non .NET defined) COM interfaces.
In the unmanaged world QueryInterface
for these interfaces works fine, however, calling methods on them never breaks into my .NET code and seems to return default values only (0).
Is it possible to Marshal a .NET object as a dual interface, such that it may be used through IDispatch
or by querying for particular interfaces? My type is public, ComVisible
and I tried applying [ClassInterface(ClassInterfaceType.AutoDual)]
without luck.
I've had no problems getting things to work using UnmanagedType.Interface
marshaling, however, supporting IDispatch
as well seems problematic. If there is an easy way to "manually" implement IDispatch
this would also be an acceptable solution.
You can use the ICustomQueryInterface interface. It will allow you to return IUnknown interfaces "manually" and still benefit from the IDispatch implementation provided by .NET. So, for example, if you have an unmanaged IUnknown interface "IMyUnknown" that contains one method (named "MyUnknownMethod" in the sample), you can declare your .NET class like this:
[ComVisible(true)]
public class Class1 : ICustomQueryInterface, IMyUnknown
{
CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv)
{
if (iid == typeof(IMyUnknown).GUID)
{
ppv = Marshal.GetComInterfaceForObject(this, typeof(IMyUnknown), CustomQueryInterfaceMode.Ignore);
return CustomQueryInterfaceResult.Handled;
}
ppv = IntPtr.Zero;
return CustomQueryInterfaceResult.NotHandled;
}
// an automatic IDispatch method
public void MyDispatchMethod()
{
...
}
// the IMyUnknown method
// note you can declare that method with a private implementation
public void MyUnknownMethod()
{
...
}
}