I connect to some program via COM and receive System.__ComObject. I know several methods of it, so I can do like this:
object result = obj.GetType().InvokeMember("SomeMethod", BindingFlags.InvokeMethod, null, obj, new object[] { "Some string" });
and like this
dynamic dyn = obj;
dyn.SomeMethod("Some string");
Both methods works fine. But how can I determine inner type information of com object and enumerate through all its members?
I tried this:
[ComImport, Guid("00020400-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch
{
void Reserved();
[PreserveSig]
int GetTypeInfo(uint nInfo, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out System.Type typeInfo);
}
...
IDispatch disp = (IDispatch)obj;
Type t;
disp.GetTypeInfo(0, 0, out t);
But the t is null at the end. Can anyone help me?
Best Answer
I've just published a CodeProject article about how to do Reflection with IDispatch-based COM objects. The article provides a small C#
DispatchUtility
helper class that's easy to include in other projects. Internally, it uses a custom declaration of IDispatch and .NET's TypeToTypeInfoMarshaler to convert IDispatch's ITypeInfo into a rich .NET Type instance.In your example, you could call
DispatchUtility.GetType(obj, true)
to get back a .NET Type instance, which you could then call GetMembers on.FWIW,
DispatchUtility
's declaration of IDispatch.GetTypeInfo is nearly identical to yours. However, when calling GetTypeInfo, it passes in LOCALE_SYSTEM_DEFAULT (2048) rather than 0 for the lcid parameter. Perhaps GetTypeInfo returned a failure HRESULT for yourdisp.GetTypeInfo(0, 0, out t)
call. Since you declared it with[PreserveSig]
, you'd need to check its result (e.g., by callingMarshal.ThrowExceptionForHR
).Here's a version of the
DispatchUtility
class with most comments removed: