2011-04-26 46 views
2

我正在構建一個需要從VBA引用的庫,所以我需要提供一個類型庫來支持早期綁定。我見過的大多數例子都定義了暴露給COM的類的接口,例如爲COM類定義接口的優點是什麼?

[Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7039")]  
[InterfaceType(ComInterfaceType.InterfaceIsDual)]  
public interface IMyClass 

[Guid("13FE32AD-4BF8-495f-AB4D-6C61BD463EA4")]  
[ClassInterface(ClassInterfaceType.None)]  
[ProgId("MyNamespace.MyClass")]  
public class MyClass : IMyClass 

讓類直接使用ClassInterface.AutoDual實現接口有什麼缺點嗎?對於更復雜的類,我喜歡使用接口來清楚地定義哪些成員暴露com,而無需到處使用ComVisible屬性。但是我也會有一些相當平凡的數據類,比如事件參數,這些參數將全部公開給COM。我也看到了一些明確設置接口不匹配的例子 - 這樣做有什麼優勢嗎?

+1

關於爲什麼你需要一個接口和'ClassInterfaceType.None',請看這個問題http://stackoverflow.com/q/1435295/57428。 – sharptooth 2011-04-26 05:26:11

回答

5

是的,有一個很大的:DLL地獄是討厭的與早期綁定。 COM客戶端通過v表指針直接調用該方法。如果過時的COM服務器使用相同的接口IID(本身就是犯罪行爲),那麼這可能會調用錯誤或不存在的方法。運行時故障(通常是AccessViolation)很難診斷。

這不會發生在後期綁定中,通常會有一個合理的診斷,如DISP_E_MEMBERNOTFOUND或DISP_E_BADPARAMCOUNT。這就是爲什麼微軟很重視ComInterfaceType.InterfaceIsIDispatch。缺點是後期綁定很慢。另一個是隻在運行時捕獲錯誤,而不是編譯時。

設置DispIDs非常少用。一些傳統的微軟產品使用了dispid綁定,將dispid預編譯成代碼。它大約是後期綁定的兩倍,因爲不需要IDispatch :: GetIDsOfNames()調用。你不太可能在野外遇到它們,當然不是任何VBA版本。

一個體面的KB文章is here主題。

+0

我看了文章 - 感謝指針。猜猜你是在談論二進制兼容性 - 所以如果我安裝一個新版本而不更新類型庫,然後通過使用接口,實現COM接口的代碼的vtable佈局保持不變,函數調用仍然工作? – Shane 2011-04-26 14:10:49

+0

我對你關於重用IID的評論有點困惑。你是什​​麼意思IID - 在我上面的例子中應用到接口的GUID?你是否在說,當你說「這本身就是犯罪」時,新版本的代碼被釋放時,應該改變界面上的GUID?這不會破壞版本之間的兼容性嗎? – Shane 2011-04-26 14:11:27

+0

我想我知道你的意思是不重新使用IID--接口應該是不可變的,即一旦IID被分配給接口,它在組件的未來版本中不應該改變 - 只能添加新的接口。它是否正確? – Shane 2011-05-04 04:52:13

相關問題