Trying to create a mapper for an Microsoft Office object to POCO’s and found this
// doesn't work
// returns an empty array where o is a RCW on an office object
foreach(var pi in o.GetType().GetProperties() )
tgt.SetValue(rc, pi.GetValue(o, null));
so have to resort to this
foreach(var field in tgt.GetFields() ){
var pv = o.InvokeMember(field.Name, System.Reflection.BindingFlags.GetProperty, null, o, null);
i.SetValue(rc, pv);
}
which works for now but wondering why the RCW.GetProperties() doesn’t work here?
The other two answers as of this writing are correct, but they miss an important opportunity to explain how the late binding of a COM object looks in terms of the .NET type system. When you call
GetTypeon the COM object, the return value is the__ComObjectinternal type, not the COM interface type that you normally work with when writing interop code. You can see this in the debugger, or with some code likeConsole.WriteLine(o.GetType().Name);.The
__ComObjecttype has no properties; that’s why you get an empty array when you callo.GetType().GetProperties(). (At least some things in life make sense!)If you decompile the
InvokeMembermethod, you’ll find that it has special handling for COM objects, delegating the call to an internal native method. For “regular” .NET objects, the method uses “regular” .NET reflection, retrieving the appropriateMemberInfofor the requested member, and invoking it.You can use .NET reflection on the interface type. For example, if you know that the object is an Excel
Worksheet, you can usetypeof(Worksheet).GetProperties(), and use the resultingPropertyInfoinstances with your object. If you don’t know the type of the object at compile time, however, you need to callGetType(), as in your example code. In that case, you’re stuck with usingInvokeMember.