1、COM對象的創建方法
客戶程序可以通過CoCreateInstance函數創建COM,在創建之前必須知道對象的一些基本情況,比如對象的CLSID或者對象的ProgID。
另一種對象創建方法是通過名字對象(moniker)創建,就是利用對象命名和綁定技術(即名字技術)。
2、名字技術的地位
名字技術算不上COM的基本核心,但也是COM體系結構中重要的組成部分,它為客戶程序和組件程序提供了另一條更為靈活的聯系紐帶。OLE的成功使名字技術得到了廣泛的應用,而且在OLE和COM的不斷發展過程中,名字技術發揮了其強大的擴展特性,異步名字對象的實現使它超越了OLE的應用范圍,能更好地適用於網絡環境,特別是Internet網絡,體現了名字技術強大的生命力。
名字技術允許客戶程序通過符號化的方式訪問組件對象,而不必通過CLSID和類廠訪問COM對象。名字技術不僅為COM對象提供了符號化的表達方式,而且它充分體現了面向對象軟件體系的一些重要概念,甚至可以把它當作軟件體系結構的一項技術來學習。
3、COM名字技術包括兩方面內容:命名技術和綁定過程
4、名字對象
名字技術的核心是名字對象,COM使用術語”moniker”來表示名字對象,它本身也是一個COM對象。名字對象為組件對象提供了符號化的表示方法,同時它也對組件對象進行了全面的封裝,客戶程序只需創建相應的名字對象,然後利用名字對象的綁定功能得到組件對象。名字對象能夠自動使組件對象從被動狀態進入運行狀態,所以名字對象也稱為永久智能名字(persistent intelligent names)。
名字對象封裝了組件對象的所有狀態處理過程,因此客戶程序可以按照統一的方法處理名字對象,即使要引用新的組件對象,客戶代碼也不必作任何改動。
5、文件名與名字對象
文件名字對象(file moniker)是一種基本的名字對象,文件名也通過符號化的字符串名指向實際的文件。文件名代表了一個磁盤文件,文件名本身不是一個對象,它只代表了文件對象的路徑,因此,文件名不具有智能特性。
COM對象的永久狀態可以是整個文件,也可以是文件的一部分。
雖然名字對象扮演了與文件名相同的角色,但名字對象的功能要強大得多。首先,它所表達的對象范圍廣闊得多,除了一般的文件對象,它也可以表達文件中的部分內容,其次,名字對象具有智能特性,即它可以使被動態的對象自動進入運行態,名字對象找到與永久狀態聯系的運行代碼,並啟動這些代碼,利用對象的初始化功能使對象進入運行狀態,這個過程就是名字對象的綁定操作。
6、名字對象的綁定過程
名字對象實現了標准的COM接口IMoniker,客戶程序通過IMoniker接口獲得組件對象。
客戶程序通過名字對象訪問組件對象可以分成兩步:第一,獲得名字對象;第二,執行名字對象的綁定操作(使用IMoniker接口的函數BindToObject),綁定過程的結果就是組件對象的接口指針。
客戶程序獲得名字對象的途徑有兩條:第一,調用COM API函數,如MkParseDisplayName和CreateFileMoniker;第二,其他對象的接口成員函數傳遞過來,或者通過其他的數據傳輸機制得到,比如通過剪貼板或拖-放操作等。
7、IMoniker
(1)名字管理函數:IsEqual、Hash、IsRunning、GetTimeOfLastChange。
(2)綁定函數:BindToObject、BindToStorage。
(3)復合名字對象管理函數:Reduce、ComposeWith、Enum、Inverse、CommonPrefixWith、RelativePathTo、IsSystemMoniker。
(4)名字解析函數:GetDisplayName、MkParseDisplayName。
8、復合名字對象
復合名字對象由一組其他的名字對象組成,也可以包括其他的復合名字對象,復合名字對象提供了一種創建任意復雜名字的機制。COM提供了一個標准的復合名字對象實現,稱為“通用復合名字對象(generic composite moniker)”,並提供了標准API函數創建此類名字對象:CreateGenericComposite。
IMoniker接口從IPersistStream派生而來,所以名字對象也是一個永久對象,它可以有自己的永久狀態。復合名字對象的永久狀態是一個流,它順序保存了每個組成名字對象的永久狀態。
通用復合名字對象按統一的方式處理它的各個成員名字對象,無論是綁定過程還是其他一些操作,如名字解析、名字簡化等。
COM使用運行對象表(ROT,running object table)表管理當前系統中正在運行的、已經被注冊的名字對象,客戶程序可調用COM API函數GetRunningObjectTable得到ROT表的IRunningObjectTable接口指針。
IMoniker接口的大多數成員函數以及其他一些API函數都包含一個被稱為綁定環境的對象,在這些函數中,以IBindCtx接口指針的形式出現。綁定環境對象主要用於名字對象的整個綁定過程,所以它包含了綁定過程所需要的一些信息。由於綁定環境對象是COM實現的系統對象,所以COM提供了一個API函數創建它:CreateBindCtx。綁定過程比較耗時,所以綁定環境對象提供了最終時間限制參數。
綁定環境對象在復合名字對象的綁定過程中有很重要的意義,一方面,通過它,綁定過程中可以取得ROT表;另一方面,通過對綁定參數的設置可以控制綁定過程的一些行為;而且利用綁定環境對象內部的對象參數可以傳遞對象信息。
9、COM名字對象分類
文件名字對象、復合名字對象、單項名字對象、反-名字對象、指針名字對象、類名字對象、URL名字對象。
文件名字對象和復合名字對象以及單項名字對象是最常被使用的名字對象,它們聯合起來幾乎可以實現絕大多數應用的對象命名和綁定過程。而反-名字對象和指針名字對象主要用於COM系統內部。
10、COM名字對象分類――文件名字對象(file moniker)
文件名字對象可以用來指定任何存儲在獨立文件中的對象,可以把它與文件系統中賦予文件的路徑名字結合起來,文件名字對象實現了從文件路徑名到代表文件的文檔對象的聯系過程。
11、COM名字對象分類――復合名字對象(composite moniker)
復合名字對象充分體現了COM命名和綁定機制的優勢,它使多個名字對象可以連接或組合在一起形成新的名字對象。由於不同類型的名字對象有可能被組合到一起,因此復合名字對象提供了連接不同名字對象空間的能力。操作系統為文件系統提供了一個公用的名字空間作為文件命名空間,因此所有的應用都按同樣的方式理解文件名。類似地,每一個容器對象為它的所屬對象都定義了其私有的名字空間。
COM把名字對象的組合方式分為通用和特定兩種。
12、COM名字對象分類――單項名字對象(item moniker)
單項名字對象用來標識一個被包含在其他對象中的對象,包含它的那個對象被稱為容器對象,對象所使用的名字空間由容器對象決定。
單項名字對象單獨存在並沒有實際意義,只有當它與其他的名字對象組合之後才真正有用。最經常的用法是,在創建了單項名字對象之後,把它與一個文件名字對象組合起來形成復合名字對象,此復合名字對象給出了對象的全路徑名。它與文件名字對象的結合可以描述文件內部的所有對象。
由於文件名字對象使用了公用的名字空間,所以所有的應用程序都可以理解文件名;而單項名字對象則使用了私有的名字空間,只有容器對象才能理解單項名字對象,一個容器對象不能理解屬於另一個容器對象的名字對象。因此,單項名字對象所指對象的容器對象必須實現IOleItemContainer接口,文件名字對象對應的組件對象還必須實現IPersistFile接口,這是文件名字對象的IMoniker::BindToObject接口成員函數所要求的。 IOleItemContainer接口把容器對象與下屬的對象聯系起來,把單項名字對象綁定到實際的對象。
單項名字對象可以用COM提供的API函數CreateItemMoniker創建。
13、COM名字對象分類――反-名字對象(anti-moniker)
通常我們在創建自定義名字對象時會用到反-名字對象,我們也可以把反-名字對象用作復合名字對象中的逆名字對象,它可以抵消掉原名字對象的作用,有如“..”在文件系統命令中所起的作用一樣。
反-名字對象可以用COM提供的API函數CreateAntiMoniker創建。
反-名字對象通常用作簡單名字對象的逆名字對象。
14、COM名字對象分類――指針名字對象(pointer moniker)
指針名字對象是一個特殊的名字對象,它所指的對象只有運行狀態,沒有被動狀態。指針名字對象只是封裝了對象的接口指針。
指針名字對象內部只管理接口指針,它沒有永久狀態。
指針名字對象可以通過調用COM提供的API函數CreatePointerMoniker創建。
15、COM名字對象分類――類名字對象(class moniker)
類名字對象標識了一個對象類,它內部封裝了對象類的標識符CLSID。雖然我們可以通過CoCreateInstance和 CoGetClassObject創建對象,但使用類名字對象不僅可以創建對象,而且它與其他的名字對象組合之後可以形成更為靈活的對象創建或綁定機制。
類名字對象可以用COM提供的API函數CreateClassMoniker創建。
16、COM名字對象分類――URL名字對象
COM給出了異步名字對象的實現模型,它允許客戶程序按異步方式執行綁定過程。在綁定進行過程中,客戶程序可以得到綁定進度信息,也允許用戶取消綁定操作。異步名字對象保持了與同步名字對象的兼容,它也允許綁定過程按同步方式進行。以前介紹的各種名字對象屬於同步名字對象,URL名字對象屬於異步名字對象。
異步名字對象與同步名字對象的區別在於,異步名字對象不僅實現了IMoniker接口,它還實現了接口 IAsyncMoniker,IAsyncMoniker只繼承了IUnknown接口,沒有增加新的成員函數,它只作為異步名字對象的標志。COM提供了API函數IsAsyncMoniker,用於判斷一個名字對象是否為異步名字對象。
URL(Uniform Resource Locator,統一資源位置)名字對象,封裝了幾個標准的Internet協議,包括“http:”、“https:”、“ftp:”和 “gopher:”。它的顯示名為URL路徑名,可以是全路徑名,也可以是部分路徑名。
URL名字對象可以利用函數CreateURLMoniker創建。
17、自定義名字對象
從結構上講,自定義名字對象只是一個支持IMoniker接口的進程內COM對象。
18、COM名字對象的應用
作為名字對象的典型應用,OLE復合文檔中的鏈接對象采用了名字對象技術,OLE復合文檔應用程序為名字對象客戶程序,鏈接對象為服務程序。
MFC對OLE的支持很全面,用名字對象實現復合文檔與鏈接對象之間的連接只是很小的一部分。