Reflect COM Interop Objects

Attempting to create a mapping for a Microsoft Office object for POCO and detecting it

// 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 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 now, but wonders why RCW.GetProperties() doesn't work here?

+6
source share
3 answers

The other two answers to this entry are correct, but they miss an important opportunity to explain how late binding of a COM object looks from the point of view of a system like .NET. When you call GetType on a COM object, the return value is an internal type of __ComObject , not the type of COM interface that you usually work with when writing interaction code. This can be seen in the debugger or with some code, for example Console.WriteLine(o.GetType().Name); .

The __ComObject type has no properties; why do you get an empty array when you call o.GetType().GetProperties() . (At least some things in life make sense!)

If you decompile the InvokeMember method, you will find that it has special handling for COM objects, delegating the call to an internal native method. For "normal" .NET objects, the method uses "regular" .NET reflection, retrieves the corresponding MemberInfo for the requested element, and calls it.

You can use .NET reflection for an interface type. For example, if you know that the object is an Excel Worksheet , you can use typeof(Worksheet).GetProperties() and use the resulting PropertyInfo instances with your object. However, if you do not know the type of the object at compile time, you need to call GetType() , as in your code example. In this case, you are stuck with InvokeMember .

+17
source

This is because the COM object has been linked recently. The runtime does not know which methods / properties will be available on the COM object until they are available / called.

Here are some good related articles:

http://support.microsoft.com/default.aspx?scid=kb;en-us;Q302902

http://www.codeproject.com/Articles/10838/How-To-Get-Properties-and-Methods-in-Late-Binding

+3
source

You need to specify them by name using Type.InvokeMember(propertyName, BindingFlags.GetProperty, binder, target, args) , because there is no way to find out what properties the recently linked object has at compile time. Instead, you need to perform this search at runtime, usually using string comparisons.

RCW.GetProperties() will only work if you can determine the properties and their locations at compile time.

+1
source

Source: https://habr.com/ru/post/910892/


All Articles