一、COM組件的目標:
COM組件的一個主要優勢是:便於升級。
要實現這個優勢需要滿足一下兩個條件:
1、運行時從客戶程序動態加載和卸載,採用DLL技術可以實現。
2、爲了更好的突出DLL的優勢,還需要信息隱藏,即封裝性。
二、COM組件的信息隱藏採用IUnknown接口來實現:
1、IUnknown接口功能簡介:
IUnknown意思是未知,即未知的接口。採用這個名字是爲了簡單起見,所有的COM接口都需要繼承IUnknown,因此若某個客戶擁有一個IUnknown接口的指針,也就不知道接口到底是什麼類型的,只需要知道此接口可以用來查詢其他接口。IUnknown接口有一個用來查詢接口的函數QueryInterface。由於所有的COM組件接口都從IUnknown接口繼承,因此所有的接口都有QueryInterface函數,通過QueryInterface可以查詢到任何接口,因此也就不需要單獨維護一個代表組件的指針。
2、QueryInterface功能簡介:
客戶可以通過IUnknown中包含的QueryInterface函數查詢某個組件是否支持某個特定的接口。
若支持,QueryInterface將返回指向此接口的指針。
否則,將返回一個錯誤代碼。
然後,客戶可以接着查詢其它接口或將組件卸載。
3、QueryInterface函數遵循的規則:
QueryInterface的實現需要遵循一些規則,以便於客戶能夠獲取關於組件的足夠多的知識並對之實施一些控制和其他有用的處理。QueryInterface的行爲必須是穩定的。
<1>、QueryInterface返回IUnknown接口時,總是返回同一IUnknown指針。
每個組件實例只有一個IUnknown接口,因此當查詢組件實例的IUnknown接口時,不論通過那個接口查詢,得到的均將是同一指針值。
總結:遵循這一規則能確定兩個接口是否指向同一組件。
<2>、客戶可以獲取曾經得到過的接口。
若對於某個給定的接口,QueryInterface曾經成功過,那麼對於同一組件的後續QueryInterface將總是成功的。
總結:若不遵循這一規則客戶將無法通過編程的方法來決定組件到底有一些什麼樣的功能。
<3>、 可以再次獲取已經擁有的接口,即通過A接口查詢A接口指針。
<4>、 客戶可以從任何接口返回到起始接口,即若通過A接口可以查詢到B接口,那麼可以通過B接口查詢到A接口(對稱性)。
<5>、若能夠從某接口獲取到某特定的接口,則從任意的接口都將能獲取此接口(傳遞性)。
若可以從A接口查詢到B接口,從B接口查詢到C接口,那麼可以從A接口查詢到C接口。
總結:這條規則使得QueryInterface是可用的,即某接口的查詢不是必須依賴於某個接口查詢。
總結:COM爲QueryInterface制定上述規則的目的使爲了使QueryInterface使用起來更爲簡單、更富有邏輯性、更一致及更具確定性。
QueryInterface定義了組件,因此是COM最爲重要的部分。組件所支持的接口集就是QueryInterface能夠返回接口指針的那些接口。
三、COM組件新舊版本的處理:
COM組件一旦發佈出去,接口將永遠保持不變。接口不變是指不能改變接口(IID),但是可以建立一個新的接口(同時再爲接口指定一個新的IID)。
1、COM組件對新舊版本的處理機制:
當QueryInterface接受到對老IID查詢時,返回老的接口。
接收到對新的IID的查詢時,它將返回新的接口查詢。
對QueryInterface而言,一個IID就是一個接口,所以同某個IID相應的接口絕不會發生變化。
對於老的接口仍然保持不變,因此已有客戶的運行將不會受到任何影響。
對於新客戶則可以自行決定使用老接口還是新接口。
這種處理多個版本的方法最有效的地方在於它是無縫的。客戶不需要做任何附加的動作,因爲接口的標誌符同其版本是完全綁定在一塊的。
2、建立一個新版本的時機:
爲了使COM處理多個版本的機制能夠起作用,當下列條件中的任何一個改變時,就應給新接口指定新的IID:
<1>、接口中函數的數目。
<2>、接口中函數的順序。
<3>、某個函數的參數。
<4>、某個函數的參數順序。
<5>、某個函數的參數類型。
<6>、函數可能的返回值。
<7>、函數返回值的類型。
<8>、函數參數的含義。
<9>、接口中函數的含義。
總結:只要是所做的修改爲導致已有客戶的正常運行,都應爲接口指定新的IID。