【问题标题】:Reflection on COM Interop objects对 COM 互操作对象的反思
【发布时间】:2012-04-01 21:15:17
【问题描述】:

试图为 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));

所以不得不求助

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

目前可行,但想知道为什么 RCW.GetProperties() 在这里不起作用?

【问题讨论】:

    标签: c# .net interop outlook com-interop


    【解决方案1】:

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

    __ComObject 类型没有属性;这就是为什么在调用o.GetType().GetProperties() 时会得到一个空数组的原因。 (至少生活中有些事情是有意义的!)

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

    可以interface 类型上使用 .NET 反射。例如,如果您知道对象是 Excel Worksheet,则可以使用 typeof(Worksheet).GetProperties(),并将生成的 PropertyInfo 实例与您的对象一起使用。但是,如果您在编译时不知道对象的类型,则需要调用 GetType(),如您的示例代码中所示。在这种情况下,您只能使用InvokeMember

    【讨论】:

      【解决方案2】:

      您需要使用Type.InvokeMember(propertyName, BindingFlags.GetProperty, binder, target, args) 按名称指定它们,因为无法知道最近绑定的对象在编译时将具有哪些属性。相反,您需要在运行时执行该查找,通常通过字符串比较。

      RCW.GetProperties() 仅在您可以在编译时确定属性及其位置时才有效。

      【讨论】:

        【解决方案3】:

        这是因为最近绑定了 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-29
          • 1970-01-01
          • 1970-01-01
          • 2017-09-02
          • 2010-09-16
          • 1970-01-01
          • 2011-06-28
          • 1970-01-01
          相关资源
          最近更新 更多