簡體   English   中英

關於COM Interop對象的思考

[英]Reflection on COM Interop objects

嘗試為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()在這里不起作用?

在撰寫本文時,另外兩個答案是正確的,但它們錯過了一個重要的機會來解釋COM對象的后期綁定在.NET類型系統方面的外觀。 在COM對象上調用GetType時,返回值是__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

這是因為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

您需要使用Type.InvokeMember(propertyName, BindingFlags.GetProperty, binder, target, args)按名稱指定它們,因為無法知道最新綁定對象在編譯時將具有哪些屬性。 相反,您需要在運行時執行該查找,通常是通過字符串比較。

只有在編譯時可以確定屬性及其位置時, RCW.GetProperties()才有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM