Consuming C# interface as IDispatch even if it does not support it

Let’s assume you have following C# interface on .NET:

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("1A6CC729-1D5C-4A5E-975E-1B34AD7AF6B4 ")]
public interface IFoo
{
    int CreateNew();
}

You implemented this interface in some object and passed it to native side as IUnknown. And now you want to consume this interface as IDispatch. Scripting is good example. But If you try to call QueryInterface for IDispatch on this interface it will return E_NOINTERFACE. Looks like you out of luck.

But if you try to open mscorlib.tlb you will find interface _Object with GUID {65074F7F-63C0-304E-AF0A-D51741CB4A8D} that inherits from IDispatch. And if you call QueryInterface for _Object you see that _Object interface is supported. And because it inherits from IDispatch it is binary compatible with it. So, you may use it as IDispatch, but QueryInterface for IDispatch will still fail and it is correct behavior.

But I assume you need interface that fully supports IDispatch. For example, component you will pass this interface will call QueryInterface for IDispatch and it will obviously fail. In this case you can create wrapper around that interface and redirect all IDispatch function to that interface and everything else will be handled by your wrapper. And I think it is more correct way to use this object even it is a bit slower but much safer.

Somebody can argue that it is much easier to change attribute InterfaceType to different value to tell .NET to support IDispatch. Well there could be problems. For example, some other piece of the code expects that object does not support IDispatch. Or it could be that this code outside of your control.

But you can go further and call GetType on _Object interface. Then you can inspect type of this object, get members, invoke them etc. If you know that .NET object supports for example IList {7BCFA00F-F764-3113-9140-3BBD127A96BB} you can query and use it.

I have source code of CoreClr from https://github.com/dotnet/coreclr and I was curious where these GUID came from. I did search it few times using different techniques and I couldn’t find GUID {65074F7F-63C0-304E-AF0A-D51741CB4A8D}. But after analyzing source code I found that GUID generated from class name. Check function GenerateClassItfGuid in file src\vm\interoputil.cpp.