关于COM Interop对象的思考

Kum*_*mar 7 .net c# outlook interop com-interop

尝试为POCO创建一个Microsoft Office对象的映射器并找到它

// 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));
Run Code Online (Sandbox Code Playgroud)

所以不得不求助于此

foreach(var field in tgt.GetFields() ){
    var pv = o.InvokeMember(field.Name, System.Reflection.BindingFlags.GetProperty, null, o, null);
    i.SetValue(rc, pv);
}
Run Code Online (Sandbox Code Playgroud)

它现在有效,但想知道为什么RCW.GetProperties()这里不起作用?

pho*_*oog 18

在撰写本文时,另外两个答案是正确的,但它们错过了一个重要的机会来解释COM对象的后期绑定在.NET类型系统方面的外观. 当您调用GetTypeCOM对象时,返回值是__ComObject内部类型,而不是您在编写互操作代码时通常使用的COM接口类型. 您可以在调试器中看到这个,或者使用某些代码Console.WriteLine(o.GetType().Name);.

__ComObject类型没有属性; 这就是你打电话时得到一个空数组的原因o.GetType().GetProperties().(至少生活中的一些事情是有意义的!)

如果您反编译该InvokeMember方法,您会发现它对COM对象有特殊处理,将调用委托给内部本机方法.对于"常规".NET对象,该方法使用"常规".NET反射,检索适用MemberInfo于请求的成员并调用它.

可以接口类型上使用.NET反射.例如,如果您知道该对象是Excel Worksheet,则可以使用typeof(Worksheet).GetProperties(),并将结果PropertyInfo实例与对象一起使用.但是,如果在编译时不知道对象的类型,则需要调用GetType(),如示例代码中所示.在那种情况下,你坚持使用InvokeMember.


Jam*_*eor 5

这是因为最近绑定了 COM 对象。运行时不知道 COM 对象上有哪些方法/属性可用,直到它们被访问/调用。

这里有一些关于这个主题的好文章:

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