亚洲成年人黄色一级片,日本香港三级亚洲三级,黄色成人小视频,国产青草视频,国产一区二区久久精品,91在线免费公开视频,成年轻人网站色直接看

系統(tǒng)數(shù)據(jù)接口及相關(guān)體系結(jié)構(gòu)的制作方法

文檔序號:6554289閱讀:1732來源:國知局

專利名稱::系統(tǒng)數(shù)據(jù)接口及相關(guān)體系結(jié)構(gòu)的制作方法
技術(shù)領(lǐng)域
:本發(fā)明涉及系統(tǒng)數(shù)據(jù)接口和相關(guān)體系結(jié)構(gòu),并且在特定實施例中涉及打印系統(tǒng)數(shù)據(jù)接口和相關(guān)體系結(jié)構(gòu)。
背景技術(shù)
:一些系統(tǒng)可包括處理數(shù)據(jù)并與各類客戶機通信的服務(wù)器。一類特別的系統(tǒng)是打印系統(tǒng),它可包括提供對作業(yè)、設(shè)備、邏輯服務(wù)器的訪問,并從各個客戶機構(gòu)成數(shù)據(jù)。諸如打印系統(tǒng)等許多當(dāng)前的系統(tǒng)具有不靈活的底層網(wǎng)絡(luò)接口,每當(dāng)需要支持新的數(shù)據(jù)類時該接口就必須被修改。此外,一些接口所要求的通信比可能需要的通信多得多,并且能在服務(wù)器上創(chuàng)建上下文,無論在什么上下文中使用諸如打印系統(tǒng)等服務(wù)器,這兩種情況都可能限制服務(wù)器的性能。其它困擾許多系統(tǒng)的問題只要是協(xié)議專屬的,就可能導(dǎo)致不靈活性、難以擴展性以及局限性。由此,本發(fā)明是出于與提供包括改良的數(shù)據(jù)接口和相關(guān)體系結(jié)構(gòu)的改良系統(tǒng)相關(guān)聯(lián)的考慮。
發(fā)明內(nèi)容本文描述了一種系統(tǒng)數(shù)據(jù)接口和相關(guān)體系結(jié)構(gòu)。各實施例可提供以下各能力中的一種或數(shù)種通用數(shù)據(jù)模型、異步客戶機和服務(wù)器調(diào)度、取消、批處理、事務(wù)式調(diào)用、并行調(diào)用、截取或反射。在一個實施例中,是在打印系統(tǒng)的上下文中使用該系統(tǒng)數(shù)據(jù)接口。圖1是示出根據(jù)一個實施例的數(shù)據(jù)接口的各個組件的高級框圖。圖2是根據(jù)一個實施例的打印數(shù)據(jù)訪問接口的高級框圖。圖3是示出根據(jù)一個實施例的進(jìn)程外通信的方面的框圖。圖4是示出根據(jù)一個實施例的安全模型的概貌的高級框圖。圖5是示出根據(jù)一個實施例的類型映射機制的框圖。圖6是根據(jù)一個實施例的公共數(shù)據(jù)接口對象訪問接口的框圖。圖7是根據(jù)一個實施例的動態(tài)類型映射的框圖。圖8是示出根據(jù)一個實施例的對象創(chuàng)建和克隆的框圖。圖9是示出根據(jù)一個實施例的抽象分層結(jié)構(gòu)的框圖。圖10是示出根據(jù)一個實施例的類分層結(jié)構(gòu)和安全的框圖。圖11是示出根據(jù)一個實施例從對象檢索的元數(shù)據(jù)的框圖。圖12是根據(jù)一個實施例的公共數(shù)據(jù)接口的示例性組件的框圖。圖13是根據(jù)一個實施例的插件模型的框圖。圖14是根據(jù)一個實施例由集合適配器服務(wù)使用的對象模型的框圖。圖15是示出根據(jù)一個實施例的框架提供的集合的框圖。圖16是示出根據(jù)一個實施例的托管與非托管對象的互操作性的框圖。圖17是示出可被用來實現(xiàn)一個或多個實施例的計算設(shè)備的示例性組件的框圖。具體實施例方式概述在以下討論中,提供了一種解決現(xiàn)有系統(tǒng)的許多缺點的新穎系統(tǒng)。在一個實施例中,在打印系統(tǒng)的上下文中描述該系統(tǒng)、其數(shù)據(jù)結(jié)構(gòu)和相關(guān)體系結(jié)構(gòu)。但是應(yīng)當(dāng)意識到并理解,可在除打印系統(tǒng)以外的其它系統(tǒng)中使用以下所描述的發(fā)明特征,而不會偏離要求保護(hù)的主題的精神和范圍。盡管所描述的打印系統(tǒng)實現(xiàn)許多功能,但是基本上所描述的打印系統(tǒng)實現(xiàn)兩個主要任務(wù)。第一,該打印系統(tǒng)管理包括一組對象及其屬性在內(nèi)的數(shù)據(jù)。第二,該打印系統(tǒng)調(diào)度打印任務(wù)以首先提交打印作業(yè),然后將打印作業(yè)發(fā)送到適當(dāng)?shù)拇蛴≡O(shè)備進(jìn)行打印。提交文檔的過程可通過從指定調(diào)用哪些組件來處理該作業(yè)的數(shù)據(jù)接口檢索配置信息來實現(xiàn)。因此,打印系統(tǒng)表示數(shù)據(jù)的方式對其操作而言可能是根本的。為實現(xiàn)這些主要任務(wù),本發(fā)明的打印系統(tǒng)使用特定接口和相關(guān)組件。與現(xiàn)有打印系統(tǒng)相比,此接口以及此接口作為其部分的打印系統(tǒng)可提供許多優(yōu)點。在以下討論中,將描述各種優(yōu)點以提供對該打印系統(tǒng)和接口的初步理解。此討論之后,題為“示例性實施例”的章節(jié)討論該打印系統(tǒng)尤其是該數(shù)據(jù)接口的具體實現(xiàn)示例。下文中所描述的數(shù)據(jù)接口支持以下能力,其中每個能力都在其自己的標(biāo)題下出現(xiàn)并被討論通用數(shù)據(jù)模型、異步客戶機調(diào)度、異步服務(wù)器調(diào)度、取消、批處理、事務(wù)式調(diào)用、并行調(diào)用、截取和反射。通用數(shù)據(jù)模型所描述的數(shù)據(jù)接口支持并可結(jié)合可被視為通用數(shù)據(jù)模型的數(shù)據(jù)模型使用。該數(shù)據(jù)模型可支持具有以下能力的對象類·屬性-任何對象都可具有任意的一組屬性??蛻魴C可指定要從任何對象檢索的任何一組屬性。僅將檢索客戶機所關(guān)注的屬性?!っ?任何對象都可支持具有任意的一組參數(shù)的一組命令?!o需修改線格式即能任意地擴展客戶機可從服務(wù)器使用的類、命令和屬性。異步客戶機調(diào)度異步客戶機調(diào)度是指數(shù)據(jù)接口的應(yīng)用程序接口(API)允許客戶機或客戶機應(yīng)用程序開始一立即將控制返回給客戶機線程的數(shù)據(jù)請求的能力,如本領(lǐng)域技術(shù)人員將會理解的那樣。當(dāng)該操作的結(jié)果是完成時,客戶機經(jīng)由回調(diào)或被通知的系統(tǒng)事件得到通知,然后它可檢索數(shù)據(jù)的結(jié)果。在所示出和描述的實施例中,并不是將此能力作為旋轉(zhuǎn)(spin)一同步阻塞的線程并允許客戶機繼續(xù)處理的無關(guān)緊要的包裝(wrapper)來提供的。相反,異步調(diào)度被下延至設(shè)備級。在較低的層次上,調(diào)用的結(jié)果是網(wǎng)卡驅(qū)動的中斷。使用這一模型簡化了在從服務(wù)器檢索數(shù)據(jù)的同時保持響應(yīng)狀態(tài)的客戶機用戶接口的設(shè)計。它還減少了客戶機上所需的線程數(shù)。這在客戶機系統(tǒng)是對另一個打印系統(tǒng)起到橋梁作用的打印系統(tǒng)時特別有益。異步服務(wù)器調(diào)度在耦合了客戶機異步地向服務(wù)器調(diào)度請求的能力的情況下,服務(wù)器可異步地服務(wù)來自客戶機的請求。如果客戶機請求服務(wù)器執(zhí)行的動作是IO綁定的(例如,它需要將數(shù)據(jù)寫到盤中,或從另一個服務(wù)器請求數(shù)據(jù)),則插件組件可發(fā)布另一個異步調(diào)用,將控制返回給服務(wù)器方的數(shù)據(jù)接口,然后在IO完成時完成該次調(diào)用。此機制可大大減少服務(wù)器上運行的線程數(shù),并可確保所有線程都在充分利用系統(tǒng)CPU。系統(tǒng)上執(zhí)行的每個線程都從該系統(tǒng)占取大量“非分頁池”(非分頁池是在物理存儲器變得有限時不能被寫出到盤中的存儲器)。系統(tǒng)中運行的每個獲得系統(tǒng)鎖的線程還在系統(tǒng)中創(chuàng)建大量“爭用”(這是在執(zhí)行線程之間切換所需的時間量和CPU資源)。因此,減少系統(tǒng)中運行的線程數(shù)是提高系統(tǒng)性能的重要機制。取消在以下所描述的實施例中,服務(wù)器上正在進(jìn)行中的調(diào)用可由客戶機在任何時候取消。這幫助客戶機向調(diào)用者提供交互式用戶界面。批處理批處理是指客戶機使用該數(shù)據(jù)接口來構(gòu)建任意的動作序列、并使該動作序列作為一個單元被發(fā)送給服務(wù)器的能力。此序列隨后被處理并在單個傳輸響應(yīng)中返回給客戶機。這些動作可包括任何類型的動作,諸如獲取和設(shè)置屬性、查詢一組屬性、對服務(wù)器對象發(fā)布命令、以及為關(guān)于服務(wù)器對象屬性的改變的通知進(jìn)行注冊。事務(wù)式調(diào)用事務(wù)式調(diào)用是指被賦予該批次必須完整地執(zhí)行、否則不改變服務(wù)器狀態(tài)的語義的批次。并行調(diào)用并行調(diào)用是指被賦予該批次中的所有項目必須并行執(zhí)行的語義的批次。這允許服務(wù)器并行地執(zhí)行長期運行的動作,它還提供該批次將執(zhí)行所有動作而無論其它動作失敗情況如何的語義。截取因為該系統(tǒng)可支持的操作和屬性是由純數(shù)據(jù)傳輸表示的,所以能夠監(jiān)視、同步響應(yīng)于及修改該系統(tǒng)的行為(稱為截取)的其它組件可被插入該系統(tǒng)中。這允許監(jiān)視軟件被插入到該系統(tǒng)中,并允許其被從該系統(tǒng)中移除。這還允許獨立硬件供應(yīng)商(IHV)擴展系統(tǒng)行為。例如,如果一隊列被停止,則相關(guān)聯(lián)的服務(wù)可能也需要被停止。對該隊列的“停止”命令可被IHV截取,它們隨即可確保在允許該停止操作完成以前該服務(wù)已被停止。截取機制還可提供事務(wù)式語義。反射反射是指系統(tǒng)所提供的檢索哪些屬性受給定對象類的支持、以及與該對象相關(guān)聯(lián)的其它信息的機制。使用此機制可檢索的信息包括,但不限于·每個屬性的類型名、字段名和數(shù)據(jù)類型;·對屬性的用法的人類可讀的描述;·對象所支持的命令、以及該命令所支持的輸入和輸出參數(shù)。每個命令都有對該命令的用法的人類可讀的描述。對于每個參數(shù),以下數(shù)據(jù)可被檢索該參數(shù)的名稱和類型,以及對該參數(shù)的人類可讀的描述。在所示出并描述的實施例中,該系統(tǒng)的反射能力是協(xié)議不可知的。此外,反射能力可被用于服務(wù)器插件的本機代碼和托管代碼實現(xiàn),并可從這兩者使用。此外,反射能力提供通過網(wǎng)絡(luò)接口執(zhí)行反射、并且不要求在客戶機上存在服務(wù)器方對象的實現(xiàn)的能力。這些及其它能力將從以下描述變得明確。示例性實施例在以下討論中,結(jié)合圖1提供對本發(fā)明的接口的高級討論。這一討論之后,提供一實現(xiàn)示例,它包含實現(xiàn)專屬的信息。應(yīng)當(dāng)意識到并理解,提供該實現(xiàn)專屬的示例只是作為如何實現(xiàn)包括上述能力的打印系統(tǒng)的一個示例。因此,可使用其它實現(xiàn)而不會偏離所要求保護(hù)的主題的精神和范圍。其它實現(xiàn)可在也可不在打印系統(tǒng)的上下文中使用,如前文所提及。圖1一般地在100處示出一種包括公共數(shù)據(jù)接口102、批處理路由器104的系統(tǒng),其中批處理路由器104包括插件表106和截取表108。系統(tǒng)100還包括消息插件110、消息服務(wù)112、集合114、各種對象116、系統(tǒng)擴展118以及所謂的“其它協(xié)作”120,其中每一個都將在以下討論。公共數(shù)據(jù)接口(CDI)公共數(shù)據(jù)接口(CDI)是到批處理路由器104的接口,它允許消息被構(gòu)建并被調(diào)度到批處理路由器。CDI還負(fù)責(zé)將響應(yīng)發(fā)送到客戶機。批處理路由器批處理路由器104接收由CDI102打包并傳入該系統(tǒng)的消息。每個消息可包括目的地為若干插件的若干操作。這些消息被異步地調(diào)度,結(jié)果進(jìn)而由批處理路由器104檢索。消息是基于標(biāo)識應(yīng)將該消息發(fā)送到哪個集合的無岐義路徑被路由的。從客戶機的角度出發(fā),單個消息可能有多個目的地。插件表插件表106跟蹤所有負(fù)責(zé)給定對象集合的消息處理插件。每個集合都由一個全局唯一標(biāo)識符(GUID)標(biāo)識。在將消息向下傳遞給對象以前,到該對象的路徑被檢查并在插件表中被查找。消息插件正確的集合一經(jīng)標(biāo)識,該組消息即被傳遞給消息插件110。消息插件110可僅僅將這些消息通過線路遠(yuǎn)程地向外發(fā)送到另一個機器。但是,更加典型的情況是,消息插件110將解釋這些消息并適當(dāng)響應(yīng)。在所示出并描述的實施例中,第三方可提供消息插件。但是,當(dāng)?shù)谌教峁┫⒉寮r,對第三方而言由消息服務(wù)提供的服務(wù)是不可用的。這將使得這一層處的插入困難得多。作為消息插件的一個主要優(yōu)點是這樣將使得原始消息的形式可用。這對允許整個消息被插件集合中繼給遠(yuǎn)程機器可能是很有用的。此外,這在獨立硬件供應(yīng)商也具有支持批處理的遠(yuǎn)程系統(tǒng),并且他們希望能夠在所接收的消息格式和他們自己的消息格式之間轉(zhuǎn)換的情況下對他們而言是一個優(yōu)點。消息服務(wù)因為基于消息的系統(tǒng)中一個主要問題是難以維護(hù)消息調(diào)用上的狀態(tài),所以提供消息服務(wù)112這一組件,以將消息分解,并將它們轉(zhuǎn)換為集合接口上較簡單的調(diào)用序列。作為示例而非限制,在所示出并描述的實施例中,消息服務(wù)可執(zhí)行以下任務(wù)·將消息分配給線程;·允許在多個延遲調(diào)用中響應(yīng)消息;·從集合中的對象檢索適當(dāng)?shù)臄?shù)據(jù)來填充消息;·正確處理操作取消;·隨時間推移高速緩存對象實例;·對象的透明鎖定;以及·針對集合中所維護(hù)的對象的反射服務(wù)。集合集合114維護(hù)一組同類的對象。該系統(tǒng)提供允許對象容易地將它們自身持久化的集合。使用集合的一個優(yōu)點是它允許獨立硬件供應(yīng)商用任意對象容易地擴展該系統(tǒng)。在所示出并描述的實施例中,集合被實現(xiàn)為從動態(tài)鏈接庫(DLL)檢索出來的COM接口。在全局程序集高速緩存中查找該DLL,并且對DllGetClassObject進(jìn)行直接調(diào)用,這就允許人們規(guī)避COM注冊,如本領(lǐng)域技術(shù)人員將會理解的那樣。對象上文和下文中所描述的系統(tǒng)的一個目的是允許獨立硬件供應(yīng)商及其它開發(fā)者在有了對其實現(xiàn)語言的直接支持的情況下,很大程度上能夠在類的層次上進(jìn)行編碼。該目的是將盡可能多的代碼并入集合中,以減少獨立硬件供應(yīng)商及其它開發(fā)者必須編寫的代碼總量。對象116是集合所維護(hù)的邏輯結(jié)構(gòu)。消息服務(wù)112提供一個層,在該層這些對象直接對應(yīng)于C++類。截取表截取表108向打印系統(tǒng)提供一種一般的、通用的擴展機制。這里的目的是允許擴展能夠截取并修改目標(biāo)為系統(tǒng)中的任何對象、特定類的對象、或特定對象實例的消息。系統(tǒng)擴展因為系統(tǒng)中絕大多數(shù)事物源自中央消息系統(tǒng),并由消息表示,所以系統(tǒng)擴展118允許該系統(tǒng)被擴展,特別是被第三方以其認(rèn)為合適的任何方式監(jiān)視。這些擴展還提供由假脫機程序團(tuán)隊本身所進(jìn)行的有用的監(jiān)視擴展。其它協(xié)作可以理解,不是所有系統(tǒng)行為都可被表示為數(shù)據(jù)驅(qū)動的消息通信系統(tǒng)。因此,創(chuàng)建了機器中的其它子系統(tǒng)的對象之間已有并還將會有其它協(xié)作120。這些可包括例如管道和調(diào)度器。這里的目的是令所有這些協(xié)作盡可能的靈活,以允許他方被插入到該系統(tǒng)中。這些其它子系統(tǒng)與該系統(tǒng)的CDI視圖保持一致的方法是通過CDI調(diào)用工廠對象,它們或是直接創(chuàng)建對象,或是返回適當(dāng)?shù)臄?shù)據(jù)以允許對象被實例化。使用此模式的結(jié)果是系統(tǒng)擴展可截取這些對工廠對象的調(diào)用,并且它們可實現(xiàn)該工廠并包裝原始接口。這意味著系統(tǒng)擴展可監(jiān)視或修改該系統(tǒng)的任何方面。這對于允許可插入的監(jiān)視組件在任意點處被插入到系統(tǒng)中是非常有用的?,F(xiàn)在提供了對本發(fā)明的接口的高級討論后,以下章節(jié)描述包含實現(xiàn)專屬信息的實現(xiàn)示例。如上文中所提及,應(yīng)當(dāng)意識到并理解,提供實現(xiàn)專屬的示例只是作為如何實現(xiàn)根據(jù)本文中所描述的發(fā)明原理的打印系統(tǒng)的一個例子。因此,可使用其它實現(xiàn)而不會偏離所要求保護(hù)的主題的精神和范圍。實現(xiàn)示例作為預(yù)備知識,貫穿此后的討論將使用以下術(shù)語和縮寫詞匯表·動作-見批次?!ぴL問適配器-見數(shù)據(jù)訪問適配器?!ぴL問器-一種用來從對象檢索數(shù)據(jù)的方法。.Net屬性是訪問器的一個例子?!づ?在被累積以后在一個時間點被執(zhí)行的一系列動作。一個批次通常會導(dǎo)致一個網(wǎng)絡(luò)調(diào)用。動作可以是獲取、設(shè)置、查詢、命令和通知請求。·批處理集合-插入批處理路由器中的最高級的接口。它接收被適當(dāng)?shù)芈酚傻囊獔?zhí)行的動作批次?!づ幚砺酚善?CDI中選擇將批次中的動作傳遞給一組集合中的哪一個的元素。·規(guī)范名稱-在時間和空間中唯一標(biāo)識對象的名稱。在CDI中這將是集合GUID和對象GUID。CDI只基于規(guī)范名稱進(jìn)行路由。應(yīng)用程序在與該系統(tǒng)通信時應(yīng)當(dāng)在任何可能之處使用規(guī)范名稱。見友好名稱。·CDI-見公共數(shù)據(jù)接口?!ゎ?在CDI中是一種對象。類可以是打印機、作業(yè)或服務(wù)器、或者任何其它邏輯劃分。類包含類型?!た蛻魴C集合-在客戶機上維護(hù)的對象集合。CDI基于對象的類型映射在客戶機集合中填充對象?!ぜ?由一段邏輯代碼提供的一組異類的對象。CDI基于規(guī)范名稱將請求路由到多個集合。·集合適配器服務(wù)-向批處理路由器公開批處理集合接口、并實現(xiàn)允許比較容易地公開一組對象的服務(wù)的服務(wù)?!っ?一種批處理動作,它在該批次最終被發(fā)送到服務(wù)器時使對象上的方法被執(zhí)行。·公共數(shù)據(jù)接口-允許經(jīng)由規(guī)范名稱訪問對象的組件。它還為將調(diào)用一起批處理以及異步或同步訪問對象提供支持?!?shù)據(jù)訪問適配器-數(shù)據(jù)訪問適配器插入到CDI中,并以某種方式轉(zhuǎn)換其能力。這可以是將CDI所公開的接口變換為另一個接口(進(jìn)程內(nèi)(In-proc)適配器),或者可以是將CDI遠(yuǎn)程化,在此情形中它是遠(yuǎn)程訪問適配器?!わ@示名稱-見友好名稱?!で度腩愋?集合中被用來動態(tài)擴展另一個集合中的另一個對象所支持的屬性的對象?!ぷ侄?一段命名的數(shù)據(jù)?!び押妹Q-也稱為顯示名稱。友好名稱是用戶將其與對象(Fred的打印機)相關(guān)聯(lián)的名稱,它與系統(tǒng)用來標(biāo)識對象實例的規(guī)范名稱相對。為了允許友好名稱被轉(zhuǎn)換為規(guī)范名稱,CDI提供名稱解析管道?!し謱咏Y(jié)構(gòu)-在CDI中它是父和子對象之間的任意關(guān)系,該關(guān)系可通過從父對象查詢鏈接來獲得。·進(jìn)程內(nèi)適配器-與應(yīng)用程序中運行的CDI實例進(jìn)程內(nèi)運行的數(shù)據(jù)訪問適配器的一種形式。這些通常僅僅是以某種方式變換數(shù)據(jù)。例如,通過提供訪問數(shù)據(jù)的API。·鏈接-用于查詢對象之間的分層結(jié)構(gòu)關(guān)系的一個特殊的保留類?!ぴ獢?shù)據(jù)-勿與CLR中的反射混淆??蓮娜魏螌ο蟛樵冊獢?shù)據(jù)以發(fā)現(xiàn)其所支持的類型、字段、和命令。無論客戶機上是否有對應(yīng)的程序集可用,它都可被檢索?!し椒?在調(diào)用一對象時該對象上獲執(zhí)行的實際代碼段。稍有不同的概念請參見命令?!っQ解析管道-在應(yīng)用程序空間中運行以將友好名稱轉(zhuǎn)換為規(guī)范名稱的一系列稱為解析器的元素?!?yōu)化的類型映射-要對兩個對象執(zhí)行以將一組字段從一個對象轉(zhuǎn)移到另一個對象的一系列獲取和設(shè)置。這是通過組合客戶機對象的類型映射和服務(wù)器對象的類型映射的字段來構(gòu)建的?!こ志脤ο蠹戏?wù)-插入到集合適配器服務(wù)中的允許對象被持久化到數(shù)據(jù)庫中的服務(wù)。·查詢-在CDI的上下文中,用可任選的過濾器與可任選的查詢基對給定類的一組對象的請求。·查詢基-查詢開始的概念點。例如,基可以是本地機器或給定的服務(wù)器?!みh(yuǎn)程訪問適配器-遠(yuǎn)程訪問適配器允許CDI所公開的接口被遠(yuǎn)程化于兩個機器之間。它通過對一個CDI表現(xiàn)為對象集合,而對被遠(yuǎn)程化的CDI表現(xiàn)為數(shù)據(jù)適配器來實現(xiàn)此目的。·解析器-名稱解析管道中的一個元素。每個解析器都與一個集合相關(guān)聯(lián),并且知道如何標(biāo)識其內(nèi)部的元素?!ゎ愋陀成?一張各字段及其相關(guān)訪問器的表,它描述如何從對象檢索數(shù)據(jù)或如何將其應(yīng)用于對象。類型映射可以是動態(tài)或靜態(tài)的。通過比較字段來產(chǎn)生優(yōu)化的類型映射,兩個類型映射可被合并?!ゎ愋?類似于接口。類型是總是必須被完整實現(xiàn)的字段和命令的邏輯分組。公共數(shù)據(jù)接口公共數(shù)據(jù)接口(CDI)提供包括根據(jù)名稱(友好名稱,或較佳的是規(guī)范名稱)來定位對象,從該對象獲得數(shù)據(jù)或?qū)?shù)據(jù)應(yīng)用于該對象,支持由對象改變觸發(fā)的通知并向?qū)ο蟀l(fā)布命令在內(nèi)的功能。CDI解決并克服各種現(xiàn)有體系結(jié)構(gòu)的許多限制,包括但不限于,同步接口的使用,缺少可擴展性,基于名稱的路由和缺少批處理,等等。CDI通過允許任意個數(shù)的可被唯一地標(biāo)識的集合被插入到該系統(tǒng)中。這些集合可支持其所希望的任何種類的對象。該接口本身具有相當(dāng)?shù)膹?fù)雜性以支持異步操作和批處理,但它提供各種服務(wù)并允許能更容易地編寫被插入的集合。路由器體系結(jié)構(gòu)調(diào)整現(xiàn)有的假脫機程序中大量基本問題都來自于路由器。這包括同步API集的使用,在啟動時加載其所有提供程序(和監(jiān)視器)的必要性,不能夠重命名對象,不能夠卸載假脫機程序的任何組件,以及不能夠關(guān)掉系統(tǒng)。這一節(jié)描述本發(fā)明的打印系統(tǒng)中的路由器的替換體系結(jié)構(gòu)。以下討論是基于圖2中所示的概覽圖。在此例中,路由器被遠(yuǎn)比其靈活的數(shù)據(jù)訪問機制,公共數(shù)據(jù)接口(CDI)所代替。CDI基本上是訪問適配器和集合之間的路由和服務(wù)層。它提供經(jīng)由多個協(xié)議在任何系統(tǒng)上定位打印對象的能力,它還提供一組允許所有對象具有相同語義的服務(wù)。這些語義是檢索和設(shè)置對象數(shù)據(jù)的子集的能力,查詢所有對象的狀態(tài)的能力,向?qū)ο蟀l(fā)布命令的能力,以及從系統(tǒng)中的所有對象一致地發(fā)送改變通知的能力。數(shù)據(jù)訪問適配器被分為進(jìn)程內(nèi)適配器和遠(yuǎn)程訪問適配器。在所示出并描述的實施例中,所有內(nèi)部組件和應(yīng)用程序(除了集合提供程序與訪問適配器以外)都僅與進(jìn)程內(nèi)適配器相接。對于跨越進(jìn)程邊界的通信以及客戶機/服務(wù)器通信,使用COM/DCOM遠(yuǎn)程訪問適配器。對于基于web服務(wù)的情形,使用SOAP適配器。各適配器進(jìn)而表現(xiàn)為其它進(jìn)程空間或其它機器上的集合。這允許任何能夠完全支持公共數(shù)據(jù)接口的訪問適配器總是可通過進(jìn)程內(nèi)適配器來訪問。圖3中示出此連接方案的概覽。下級和上級協(xié)議訪問上級適配器是任何能夠完整封裝整個公共數(shù)據(jù)接口的適配器——唯一的完全進(jìn)程內(nèi)適配器將會是基于屬性的托管代碼適配器。到該系統(tǒng)的托管API將僅代表該系統(tǒng)能力的有用應(yīng)用程序子集。有兩種類型的完全遠(yuǎn)程訪問適配器,包括用于本地機器上以及基于客戶機-服務(wù)器的情形中的通信的進(jìn)程外COM適配器,以及經(jīng)由web服務(wù)提供對數(shù)據(jù)的訪問的SOAP遠(yuǎn)程訪問適配器。適配器的其它候選有能使用公共數(shù)據(jù)接口的所有能力的適配器,它們本身僅公開有限的數(shù)據(jù)類型,但這些有限的數(shù)據(jù)類型能以完全數(shù)據(jù)驅(qū)動的方式被映射。例如,可使MOF文件數(shù)據(jù)類型和公共數(shù)據(jù)接口數(shù)據(jù)類型之間的映射成為完全數(shù)據(jù)驅(qū)動的映射。MOF文件是被Windows管理規(guī)范(WMI)系統(tǒng)用來描述系統(tǒng)對象的。其它靈活性較差的協(xié)議很可能使用進(jìn)程內(nèi)適配器來與打印系統(tǒng)組件通信,例如,RPC客戶機將經(jīng)由C++模板庫與新的打印系統(tǒng)通信。通過提供存儲器內(nèi)集合并允許用戶編寫托管類和對象適配器來向系統(tǒng)提供數(shù)據(jù),可簡化對下級提供程序的支持。下級提供程序?qū)⒈仨氈С诸愋偷哪硞€有限子集以使其可供系統(tǒng)使用。公共數(shù)據(jù)接口對象模型在所示出并描述的實施例中,公共數(shù)據(jù)接口(CDI)具有如下屬性。CDI支持在對象上獲取與設(shè)置單個屬性。它還支持基于查詢過濾器和要從每個對象檢索的一組屬性來查詢對象組。CDI支持要求對象執(zhí)行命令,將一組參數(shù)傳遞給對象,并從其接收一組返回參數(shù)。此外,CDI支持請求對象改變的通知。該通知包括過濾器以及調(diào)用者想要被通知的一組屬性。此外,CDI是僅為進(jìn)程內(nèi)的,而將接口遠(yuǎn)程化的能力是由適當(dāng)?shù)牟寮m配器提供的。CDI使用回調(diào)來進(jìn)行通知;通知帶來了一些困難的權(quán)衡,因為由客戶機維護(hù)的連接顯著地降低服務(wù)器的可伸縮性。為解決這一問題,可使用兩類通知第一,管理通知可使用異步接口維護(hù)到服務(wù)器的連接。這些通知將被用于傾向于具有管理目的的頻繁改變的數(shù)據(jù),例如查看邏輯隊列中的作業(yè);第二,狀態(tài)改變通知可使用TTL方案和消息通信系統(tǒng)(例如,MSMQ)來發(fā)送具有傳遞保證的不那么頻繁的通知。因為該通知機制將支持服務(wù)器方的查詢,所以可通過指定服務(wù)器方查詢并使用有保證的傳遞機制來實現(xiàn)通常所需的用戶通知。此外,CDI是基于訪問器的。它并不公開字典接口。相反,它提供查詢機制用于獲取數(shù)據(jù),并提供了檢索對象元數(shù)據(jù)用于仿真字典接口的能力。CDI還將若干對象集合聚集在一起。上級集合被用來提供完全查詢支持。下級集合被用來提供枚舉支持,因為所有打印集合看上去都應(yīng)該是相同的;查詢是通過枚舉所有對象并對它們應(yīng)用過濾器來構(gòu)建的。任何不是CPU綁定的方法都可被異步地調(diào)用。公共數(shù)據(jù)接口允許對對象集合的訪問。所有CDI對象都是通過集合來訪問的。每個集合允許對一組對象類的訪問。對象類標(biāo)識例如邏輯設(shè)備、協(xié)議適配器、邏輯服務(wù)器等對象的類。對象類是用編程名稱來標(biāo)識的。編程名稱必須是<Company>.<Class>[.<Version>]的形式??稍谌魏螀^(qū)域設(shè)置中使用此名稱來標(biāo)識對象。該串可被實現(xiàn)為Unicode串,盡管在其它實現(xiàn)中它可由英文標(biāo)識符組成。在所示出并描述的實施例中,一類特定的對象將總是由在系統(tǒng)的整個生命期上都相同的編程名稱來標(biāo)識的,包括服務(wù)器任何先前的版本,或表示下級服務(wù)器的任何集合。給定的對象類包含若干類型。類型是以標(biāo)識對象類的相同方式由編程名稱標(biāo)識的。類型包含若干個字段——每個字段由程序字段名和字段類型標(biāo)識。類型中的諸字段在操作系統(tǒng)的所有版本上、以及在任何平臺上都必須是不變的。類型除字段外還封裝命令。命令是由串標(biāo)識的,它取若干有序的輸入和輸出參數(shù)。CDI允許對由第三方通過CDI發(fā)送的消息的截取和擴展。這將允許這些第三方監(jiān)視和擴展對象能力。對象還將被允許將某些調(diào)用重定向到被包含的對象。對象命名在所示出并描述的實施例中,對象總是具有唯一的規(guī)范名稱,它準(zhǔn)確地標(biāo)識該對象的實例——此規(guī)則唯一的例外是對于表示下級服務(wù)器上的對象的集合。對象是由對象路徑標(biāo)識的。對象路徑總是以它被包含在其中的集合實例的GUID開始,因此{(lán)XXXXXXX}\{YYYYYY}是指集合{XXXXX}中GUID為{YYYYY}的對象。對于上級服務(wù)器上的對象,路徑將會是{WWWWW}\<server>\{XXXXX}\{YYYYY},其中{WWWW}是遠(yuǎn)程集合GUID,而{XXXXX}是對象{YYYYY}位于其中的遠(yuǎn)程集合。每個CDI實例都支持默認(rèn)集合的概念,默認(rèn)集合類似于文件系統(tǒng)中的當(dāng)前路徑。因此,寄宿在應(yīng)用程序空間中的CDI可將其默認(rèn)集合設(shè)為本地機器上的假脫機程序,正如所有衛(wèi)星沙箱(satellitesandbox)進(jìn)程和應(yīng)用程序域所能夠的那樣。任何不帶完全限定路徑的對象規(guī)范名稱將在默認(rèn)集合中被自動搜索。如果在應(yīng)用程序空間(例如,繞過本地服務(wù)的對服務(wù)器的直接網(wǎng)絡(luò)訪問)中實現(xiàn)的集合要被訪問,則應(yīng)當(dāng)使用完全限定路徑(即,以‘\’開頭的路徑)。在所示出并描述的實施例中,以下是對象路徑中的保留字符‘\’、‘’、‘”’、‘^’和‘.’。脫字符(^)被用來將接下來的一個字符轉(zhuǎn)義,并允許串中可表示任何字符。下表中示出有效的轉(zhuǎn)義。因此,為了分離出在路徑中必須包含‘\’的對象名,‘\’可由‘^\’轉(zhuǎn)義。友好名稱和名稱解析管道還可任選地給予對象友好名稱(或顯示名稱)??偸菓?yīng)當(dāng)使用以下機制來定位對象?!轱@示目的,應(yīng)對服務(wù)進(jìn)行對象類的無基查詢。所有匹配這個類的本地對象將被返回。UI從該時起應(yīng)使用被返回的對象的規(guī)范名稱,并顯示這個類的顯示名稱?!τ诳杀恢苯虞斎氲接脩艚缑嬷械拿Q(包括遠(yuǎn)程服務(wù)器UNC名稱),可提供一系列稱為名稱解析器的可插入組件。應(yīng)用程序調(diào)用這些組件以將“友好名稱”解析為規(guī)范名稱?,F(xiàn)有的API將使用名稱解析器來將諸如OpenPrinter和ClosePrinter等基于友好名稱的調(diào)用轉(zhuǎn)換為規(guī)范名稱形式(因為名稱解析很可能是緩慢的,所以必須引入高速緩沖層)。·名稱解析器的順序?qū)⒈硎窘o定的名稱映射的優(yōu)先級。例如,當(dāng)遠(yuǎn)程UNC名稱被升級到連接時,同一個名稱將解析到本地集合中的邏輯隊列對象,而不是表示遠(yuǎn)程隊列的隊列對象?!?yīng)用程序可選擇是僅使最完整特征化的名稱綁定被返回給它,還是使對應(yīng)于友好名稱的所有名稱綁定被返回給它。返回所有的名稱綁定將會是成本更高的,因為它可能需要加載許多集合來進(jìn)行解析?!び辛嗣Q解析元素可防止不必要地加載整個集合,這和現(xiàn)有的路由器體系結(jié)構(gòu)不同。每個想要為其對象支持友好名稱的集合也必須實現(xiàn)名稱解析元素?!?yīng)用程序在執(zhí)行名稱解析時還將被允許指定意圖。例如,管理應(yīng)用程序可指定它只想要未經(jīng)高速緩存的信息。在此情形中,未經(jīng)高速緩存的對象將被返回,即使它的能力低于已被緩存的版本。安全在所示出并描述的實施例中,安全被密切地聯(lián)系到將由系統(tǒng)提供的服務(wù)層。但是在這里給出安全將如何起效的概述,因為它是重要的主題,并且在討論實現(xiàn)以前,對該模型的全局概述是合乎需要的。圖4示出根據(jù)一個實施例的新的假脫機程序安全模型的概念圖。這一新的假脫機程序安全模型的一個目的是保持CDI是到對象的輕量級內(nèi)部接口,因此它不執(zhí)行任何驗證功能。此外,CDI可經(jīng)由遠(yuǎn)程集合將數(shù)據(jù)路由到服務(wù)器。然后由服務(wù)器執(zhí)行授權(quán)。因此,根據(jù)本實施例,CDI路由層將不提供授權(quán)功能。最后,CDI還將在既不需要驗證也不需要授權(quán)的應(yīng)用程序空間中執(zhí)行。因此,驗證是由遠(yuǎn)程訪問適配器以與訪問傳輸和協(xié)議一致的方式執(zhí)行的,而授權(quán)是由適當(dāng)?shù)募戏?wù)(或延遲到遠(yuǎn)程服務(wù)器)執(zhí)行的。此方案的一個后果是CDI以及所有集合都可由未經(jīng)授權(quán)的用戶訪問。為幫助緩解此問題,邏輯系統(tǒng)對象提供控制對機器的整個打印系統(tǒng)的訪問的訪問控制列表(ACL)。當(dāng)遠(yuǎn)程訪問適配器接收到一批命令時,它對邏輯系統(tǒng)對象執(zhí)行訪問檢查。這些命令(如獲取、設(shè)置和查詢)只有在訪問檢查成功的情況下被允許執(zhí)行。此操作為遠(yuǎn)程訪問適配器接收到的任何批處理命令執(zhí)行一次。在所示出并描述的實施例中,邏輯系統(tǒng)ACL默認(rèn)為“每個人”(但不是“匿名的”)。管理員被允許改變邏輯系統(tǒng)許可,以限制對整個打印子系統(tǒng)的訪問。在所示出并描述的實施例中,對邏輯系統(tǒng)對象有遠(yuǎn)程訪問適配器被要求無需授權(quán)即通達(dá)邏輯機器對象的特殊的保留系統(tǒng)重置命令。邏輯機器對象僅允許管理員執(zhí)行此命令,并且它將管理員加回到邏輯機器ACL中。此機制防止管理員拒絕他或她自己對邏輯機器對象的許可,此拒絕將導(dǎo)致管理員再也不能重新訪問該子系統(tǒng)。在所示出和描述的實施例中,本地集合中的每個對象都有與之相關(guān)聯(lián)的一個ACL。對對象的訪問檢查準(zhǔn)確地包含對照其ACL檢查訪問。每個對象實例都具有一個類對象,該類對象將為該類的新對象提供默認(rèn)的可繼承的ACL,而CDI維護(hù)類對象的集合。管理員可自由修改類ACL,類ACL將為給定類的任何新對象提供默認(rèn)的ACL。這允許管理員將對對象的創(chuàng)建權(quán)委托給另一個用戶,但在對象被創(chuàng)建時仍將默認(rèn)的ACL應(yīng)用于該對象。在所示出并描述的實施例中,CDI提供允許盡可能容易地編寫本地對象集合的服務(wù)層。該服務(wù)層向任何對象實現(xiàn)提供該安全基礎(chǔ)結(jié)構(gòu)供其免費使用。圖4中沒有示出許可代理,它在許可改變時將新的ACL遞歸地應(yīng)用于所有參與的類。此代理負(fù)責(zé)將對類對象的改變傳播到類的實例,它還負(fù)責(zé)將任何管理分層結(jié)構(gòu)改變傳播到對象實例。CDI訪問器模型此接口更加基礎(chǔ)的方面之一是訪問器模型。此機制允許公共數(shù)據(jù)接口和集合填充調(diào)用者的數(shù)據(jù)結(jié)構(gòu)。在所示出并描述的實施例中,CDI訪問器模型是非托管的,因為它預(yù)期與之協(xié)同操作的打印假脫機程序包含非托管的核心服務(wù)。因為該打印系統(tǒng)的一些組件將會是托管的,并需要對打印系統(tǒng)中的數(shù)據(jù)的完全訪問,所以其中也有托管代碼訪問層。CDI訪問器模型后面的想法是CDI是一個客戶機對象集合與多個服務(wù)器對象集合之間的代理。它提供一種高效的機制,使客戶機和服務(wù)器能僅使用每一方想要傳送的字段來交換此信息。例如,考慮圖5,該圖示出在服務(wù)器集合、客戶機集合和CDI的上下文中,根據(jù)一個實施例將如何實現(xiàn)此功能的諸方面。在此例中,服務(wù)器和客戶機都描述它們想要經(jīng)由相同的機制——類型映射來公開或檢索的數(shù)據(jù)。類型映射描述每個對象所支持的各種子類型和字段。對于每個字段,提供了知道如何獲取或設(shè)置其所描述的類的每個實例的給定屬性的接口。因此,給定了類型映射,類實例的所有屬性就都可被訪問。給定對客戶機和服務(wù)器類的描述,CDI可執(zhí)行很好的優(yōu)化。特別地,CDI可匹配來自客戶機類型映射和服務(wù)器類型映射的每個字段和類型,并創(chuàng)建僅包含訪問接口的優(yōu)化類型映射。當(dāng)對兩個對象實例執(zhí)行此優(yōu)化類型映射時,所有被請求的數(shù)據(jù)在無需任何中間存儲或任何數(shù)據(jù)查找的情況下在兩個對象之間傳送。優(yōu)化類型映射的目的是利用目標(biāo)對象具有規(guī)則結(jié)構(gòu)這一事實。對于給定集合,服務(wù)器方對象具有規(guī)則的結(jié)構(gòu)。對于給定的查詢,一般希望從系統(tǒng)中所有對象獲得相同的數(shù)據(jù)。因此,特定源對象類和特定目標(biāo)對象類之間的綁定總是相同的。此外,因為源和目標(biāo)對象最終是系統(tǒng)組件,并且它們本身是規(guī)則的結(jié)構(gòu),所以每個對象實例都能以輕量級的方式來存儲。進(jìn)一步考慮,在僅有一個服務(wù)器對象可供從其檢索數(shù)據(jù)的情況下,這將是足夠的。但是,在實踐中,可能有兼容的服務(wù)器對象的許多實現(xiàn),且每種實現(xiàn)都具有一種類型映射。因此,當(dāng)客戶機向CDI注冊其類型映射時,CDI為優(yōu)化類型映射創(chuàng)建可根據(jù)GUID查找的存儲空間。服務(wù)器方隨即按需存儲每個優(yōu)化映射。目的是客戶機在應(yīng)用程序啟動時注冊其映射。然后該系統(tǒng)在客戶機開始檢索數(shù)據(jù)時圍繞該特定客戶機類型構(gòu)建一組優(yōu)化。模板派生的類型映射為類實例創(chuàng)建訪問對象可能導(dǎo)致許多代碼要被編寫,因為每個接口后的每個實例都只知道如何訪問一個屬性。通過允許每個實例使用數(shù)據(jù)來訪問服務(wù)器和客戶機中的屬性(例如,字段偏移量可被用來訪問許多對象上普遍具有的字段),可省去大量工作。這樣做大大減少了必須被編碼的訪問對象實現(xiàn)的個數(shù)。在所示出并描述的實施例中,CDI還提供模板庫,它允許用戶定義類,創(chuàng)建若干方法或字段,然后編寫一張公開他們想要定義的任何字段或方法的表。該模板機制從類字段類型或方法簽名中直接提取類型信息,并自動構(gòu)建訪問對象實例。這允許客戶機(或服務(wù)器)在無需編寫IDL的情況下公開對象。然后該對象在該打印系統(tǒng)所支持的任何傳輸上受到支持,并將自動獲得異步調(diào)用的益處。以下代碼節(jié)選示出定義客戶機想要從服務(wù)器檢索的結(jié)構(gòu)的最簡單的機制,其中省略了出錯處理。#include<iatl.h>structClientPrinter{ULONGStatus;BSTRName;BSTRLocation;BSTRComment;};IMG_ATTR_TABLE_BEGIN(ClientPrinter,TypeMap)Type("Micrsoft.Printer.Basic"),Field(IMG_ATTR_FIEL(Status)),Field(IMG_ATTR_FIELD(Name)),Field(IMG_ATTR_FIELD(Location)),Field(IMG_ATTR_FIELD(Comment)),IMG_ATTR_TABLE_ENDvoidInitializeTypeMap(Void){IImgCommonData*pICDI=NULL;IImgTypeMap*pITypeMap=NULL;CoCreateInstance(CLSID_ImgCommonData,NULL,CLSCTX_INPROC_SERVER,IID_IImgCommonData,Reinterpret_cast<void**>(&pICDI));Img::iatl::RegisterTypeMap(pICDI,IMG_ATTR_TABLE(ClientPrinter,TypeMap),&pITypeMap);////Dostuffwiththetypemap.//pICDI->Release();pITypeMap->Release();return0;}類型映射機制也允許調(diào)用者指定方法。以下代碼節(jié)選示出在此情形中方法可被如何定義,其中省略了出錯處理。ClassServerClass{IMG_ATTR_TABLE_FRIEND(ServerClass,TypeMap);private:HRESULTSetComment(BSTRnewComment){BSTRtempComment=SysAllocString(newComment);if(tempComment){SysFreeString(Comment);Comment=tempComment;ReturnS_OK;}returnE_OUTOFMEMORY;}BSTRGetComment(Void){returnComment;}BSTRComment;};IMG_ATTR_TABLE_BEGIN(ServerClass,TypeMap)Type("Microsoft.Printer.Basic"),Field(IMG_ATTR_METHOD(ServerClass::SetComment),"Comment",gGetMethod),Field(IMG_ATTR_METHOD(ServerClass::GetComment),"Comment",gSetMethod),.........IMG_ATTR_TABLE_END在所示出并描述的實施例中,模板庫支持一組從CDI類型到C++類型的核心映射。該庫可由第三方擴展,從而新的類型可在任何時候被引入或改進(jìn),而根本無需改變模板庫的任何部分。使用公共數(shù)據(jù)接口此節(jié)中給出的素材擴充了以上所描述的素材,但前者在更加低的等級進(jìn)行描述。本文檔的其余部分專供對根據(jù)一個實施例的CDI的使用和實現(xiàn)的低級描述。CDI類型CDI類型系統(tǒng)被設(shè)計成支持該系統(tǒng)提供保證的許多標(biāo)準(zhǔn)類型(例如,它們在該系統(tǒng)所支持的任何協(xié)議上起效,并且其中大多數(shù)可被用于查詢)。CDI類型系統(tǒng)還提供在設(shè)計時創(chuàng)建新類型并在運行時在系統(tǒng)中使用這些新類型的機制。為此目的,如在以下代碼節(jié)選中所示地定義了ImgVariant類型。和系統(tǒng)Variant相似,它具有類型和未命名的聯(lián)合。但是它支持一組與系統(tǒng)Variant非常不同的基本類型,如下表所示。////這是復(fù)制者的基本變量類型。僅在兩個對象之間的轉(zhuǎn)換中使用。//typedefstruct_tagImgVariant{ImgTypetype;union{ULONGuLongVal;ULONGLONGuLongLongVal;BSTRbstrVal;IImgImutableString*refStrVal;DOUBLEdoubleVal;IStream*pXMLStreamType;IImgCanonicalName*pINameVal;IImgMultiValuedName*pIMultiNameVal;ImgMultiStringmultiStringVal;////這兩個類型允許系統(tǒng)的其它用戶在ImgVariant中存儲他們自己的數(shù)據(jù)。保證支持最多至128位的任何//值類型,或者指針。//void*pOtherVal;unsignedcharspace[16];};}ImgVariant;另一個不同之處是ImgVariant類型是可擴展的。這是通過不將ImgType定義為聯(lián)合,而將其定義為指針來實現(xiàn)的。此聲明在以下代碼節(jié)選中示出。////用來保留類型實例的結(jié)構(gòu)。//typedefstruct{ULONGdummy;}ImgTypeReservation;////類型被描述為指向保留的存儲器段的指針//typedefImgTypeReservation*ImgType;為了保留新類型的枚舉,就定義ImgTypeReservation全局變量,且其地址成為所定義的類型的有保證的唯一標(biāo)識符。類似地,系統(tǒng)將定義其自己的類型為全局唯一的指針。這使用加載器來保證這些類型在任何地址空間上都不會沖突。在所示出并描述的實施例中,該打印系統(tǒng)提供以下操縱Variant的方法。interfaceIImgCommonData:IUnknown{HRESULTVariantInitialize(INOUTImgVariant*pImgVariant);HRESULTVariantCopy([in,out]ImgVariant*pVariantDest,[in]constImgVariant*pVariantSource);HRESULTVariantClear(INOUTImgVariant*pImgVariant);HRESULTVariantConvert([in,out]ImgVariant*pVariantDest,[in]constImgVariant*pVariantSource,[in]ImgTypedesiredType);};新的CDI原子類型CDIImgVariant類型本身可包含由CDI定義的一些新的類型。按照順序,這些是IImgImutableString這是引用計數(shù)的串。此類型將被CDI自由轉(zhuǎn)換為BSTR或從BSTR轉(zhuǎn)換,且其提供對串的高效操縱。它的接口和創(chuàng)建函數(shù)在以下代碼節(jié)選中示出。typedefenum{FreeThreaded,SingleThreaded}EImgThreading;interfaceIImgImutableString:IUnknown{constwchar_t*Value(void);HRESULTNewInterface([in]EImgThreadingclientType,[out]IImgImutableString**ppINewString);};interfaceIImgCommonData:IUnknown{HRESULTImgCreateString(INconstwchar_t*string,OUTIImgImutableString**ppIString);}Value方法返回指向在不可變串內(nèi)所維護(hù)的串的指針。調(diào)用者不能修改該值,但可以自由讀取該值。它的地址不會改變,并且在該串引用被維護(hù)時,它不會被釋放或修改。NewInterface方法允許調(diào)用者請求到同一個串的新接口。這對隔離引用計數(shù)問題是有用的。調(diào)用者可請求到該串的單線程接口。在此情形中,對新接口的引用計數(shù)不會被互鎖。如果調(diào)用者知道它將在單線程上下文中對該串進(jìn)行大量操縱,則這可允許它們提高其性能。由ImgCreateString創(chuàng)建的初始串總是自由線程的。IImgCanonicalName此類型由插件內(nèi)部使用以提供對其它類型的規(guī)范名稱引用。此類型在以下代碼節(jié)選中示出。typedefenum{AbsolutePath,RelativePath,ObjectRelative,CollectionRelative,ServerRelative}EImgPathType;interfaceIImgCanonicalName:IUnknown{ULONGPathFieldCount(void);HRESULTPathField([in]ULONGcElem,[out]IImgImutableString**ppIString);HRESULTPath([out]BSTR*pbstrPath);EImgPathTypePathType(void);HRESULTNewInterface([in]EImgThreadingclientType,[out]IImgCanonicalName**ppINewCanonicalName);};interfaceIImgCommonData:IUnknown{HRESULTCreateCanonicalName([in]constwchar_t*path,[out]IImgCanonicalName**ppICanonicalName);HRESULTCreateCanonicalNameFromStrings([in]EImgPathTypepathType,[in]ULONGcElems,[in]IImgImutableString**paString,[out]IImgCanonicalName**ppICanonicalName);}規(guī)范名稱包含對象路徑的經(jīng)語法分析的元素。每個元素都作為不可變串被存儲。規(guī)范名稱或可從路徑創(chuàng)建,或可從一組不可變串直接構(gòu)造。例如,對于路徑“\{GUID}\abc^\def”,規(guī)范名稱將包含兩個串“{GUID}”和“abc\def”。該接口還允許調(diào)用者從規(guī)范名稱的子串構(gòu)造路徑,例如,它們可用串“ab\\cd”、“efg”創(chuàng)建規(guī)范名稱,然后獲得路徑“ab^\^\cd\efg”。和不可變串一樣,規(guī)范名稱是不可變的,并且可為線程或引用計數(shù)目的從其獲得新的別名接口。IImgMultiValuedName多值名稱被用來將用規(guī)范名稱的引用返回給數(shù)個不同的對象。它被用來表示兩個對象類之間的1-N或N-N關(guān)系。其接口在以下代碼節(jié)選中示出。typedefstruct{ULONGcNames;BSTR*abstrNames;}ImgMultiString;interfaceIImgMultiValuedName:IUnknown{ULONGNameCount(void);HRESULTNameField([in]ULONGcElem,[out]IImgCanonicalName**ppIName);HRESULTGetNamesAsStrings([out]ImgMultiString*MultiString);HRESULTNewInterface([in]EImgThreadingclientType,[out]IImgMultiValuedName**ppINewMultiValuedName);};interfaceIImgCommonData:IUnknown{HRESULTCreateMultiValuedName([in]ULONGcNames,[in]IImgCanonicalName**ppINames,[out]IImgMultiValuedName**ppIMultiValuedNames);HRESULTFreeMultiString([in]ImgMultiString*String);HRESULTCreateMultiValuedNameFromMultiString([in]constImgMultiString*Strings,[out]IImgMultiValuedName**ppIMultiValuedNames);}多值名稱可從一組規(guī)范名稱構(gòu)造,并且每個規(guī)范名稱都可被檢索。和不可變串及規(guī)范名稱接口一樣,它也是不可變的,并且可為引用計數(shù)或線程原因獲得到它的新接口。因為導(dǎo)航這些接口對調(diào)用者而言較為復(fù)雜,所以多值名稱提供一種通過GetNamesAsStrings接口獲取整個封閉的規(guī)范名稱作為BSTR路徑數(shù)組的機制。為了釋放所返回的多串,ImgFreeMultiString調(diào)用被使用。此外,調(diào)用者可從路徑的多串直接得到多名。這對于從一組靜態(tài)路徑構(gòu)造多值名稱特別有用。注冊新的Variant類型標(biāo)準(zhǔn)Variant將總是在線路上正確封送,并且在系統(tǒng)所使用的查詢語言中全部都有支持。但是,特別是對于進(jìn)程內(nèi)情形而言,擴展Variant類型將會是非常有用的。這允許創(chuàng)建諸如點等新的值類型、或是無需被轉(zhuǎn)換為串的可打印區(qū)域。或者,它允許定義可作為命令的一部分被檢索和操縱的接口。為此目的,CDI提供一種擴展可由VariantCopy、VariantClear和VariantConvert處理的Variant的機制。此接口在以下代碼節(jié)選中示出。interfaceIImgVariantExtender:IUnknown{HRESULTVariantCopy([in,out]ImgVariant*pDest,[in]constImgVariant*pSrc);HRESULTVariantClear([in]ImgVariant*pVariant);HRESULTVariantConvert([in,out]ImgVariant*pDest,[in]constImgVariant*pSource,[in]ImgTypedesiredType);}typedefstruct{ImgTypeinputType;ImgTypeoutputType;}ImgVariantTypeConversion;typedefstruct{ULONGcImgVariantTypes;[size_is(cImgVariantTypes)]constImgType*aTypes;ULONGcImgVariantConversions;[size_is(cImgVariantConversions)]constImgVariantTypeConversion*aTypeConversions;}ImgVariantTypeExtensionData;interfaceIImgVariantExtensionRegistration:IUnknown{};interfaceIImgCommonData:IUnknown{HRESULTRegisterVariantExtension([in]constImgVariantTypeExtensionData*ExtensionData,[in]IImgVariantExtender*pIExtender,[out]IImgVariantExtensionRegistration**ppIRegistration);}在此,需要在IImgVariantExtender接口中提供知道如何對所注冊的類型執(zhí)行所有這些操作。然后還要提供該接口所支持的一組類型、以及該接口將執(zhí)行的一組轉(zhuǎn)換。然后該系統(tǒng)將把它對Variant類型的處理擴展為包括為已被指定的類型調(diào)用這些接口。如果提供了到標(biāo)準(zhǔn)Variant類型和從標(biāo)準(zhǔn)Variant類型的轉(zhuǎn)換,則遠(yuǎn)程化層也將在線路上正確封送適當(dāng)?shù)臄?shù)據(jù)。這允許在和服務(wù)器對象相同的進(jìn)程內(nèi)或在線路上透明地使用類型。注冊類型映射客戶機類型映射一經(jīng)構(gòu)造,它就被注冊到CDI,并且一表示該類型映射注冊的接口被返回給客戶機。此對象聚集用來綁定到各個集合類的優(yōu)化類型映射。目的是允許進(jìn)程預(yù)先注冊所有它打算使用的類型,然后從那時起便能夠使用給定的類型映射。當(dāng)優(yōu)化類型映射被構(gòu)建時,從對象查詢數(shù)據(jù)所需的時間就變得很少,因為無需比較任何字段。用于注冊類型映射的完整接口在以下代碼節(jié)選中示出。interfaceIImgAccessor;typedefenum{////Bind-timediscoverableerrors,//SourceTypeDoesNotExist=0x00000001,SourceFieldDoesNotExist=0x00000002,SourceFieldTypeIncompatible=0x00000004,////Dynamicerrorsandproperties,//SourceDataDoesNotExist=0x00010000,Private=0x00020000,Modified=0x00040000,CollectHistory=0x00080000}EImgCopyFlags;typedefstruct{EImgCopyFlagsflags;}ImgExtraCopyData;typedefstruct{[string]constwchar_t*type;[string]constwchar_t*field;ImgTypefieldType;IImgAccessor*pIAccessor;[string]constwchar_t*description;int_ptrtag;}ImgFieldAccess;typedefstruct{ULONGcAccessors;ImgFieldAccess*aAccessors;}ImgFieldAccessors;typedefstruct{ImgFieldAccessorsinputFields;ImgFieldAccessorsoutputFields;ImgCommandsDescriptioncommands;}ImgClassDescription;[local]interfaceIImgAccessor:IUnknown{HRESULTFunction([in]void*pObject,[in,out]ImgVariant*pData,[in,out]ImgExtraCopyData*pExtra);};[local]interfaceIImgTypeMap:IUnknown{};[local]interfaceIImgCommonData:IUnknown{HRESULTRegisterTypeMap([in]ImgClassDescription*ClassDescription,[out]IImgTypeMap**ppITypeMap);};因為此接口使用了若干類型,所以以下考察其中每一個類型。EImgCopyFlags這些標(biāo)志與復(fù)制操作相關(guān)聯(lián),它讓客戶機了解在復(fù)制數(shù)據(jù)時遇到的任何問題。其中大多數(shù)標(biāo)志是意義自明的。其中一些較值得關(guān)注的標(biāo)志有·Private-該數(shù)據(jù)不應(yīng)被復(fù)制到系統(tǒng)以外。被視為該系統(tǒng)的一個部分的其它進(jìn)程可接收該數(shù)據(jù)。該數(shù)據(jù)將永遠(yuǎn)不會在線路上發(fā)送?!otModified-指示該數(shù)據(jù)仍是與服務(wù)器上的版本一致而未被修改。這對優(yōu)化一組操作而言可能是有用的。·CollectHistory-這個標(biāo)志向CDI指示對此字段的改變的歷史應(yīng)被收集。默認(rèn)行為是折疊字段的歷史數(shù)據(jù)。ImgExtraCopyData這被傳遞給訪問器以允許標(biāo)志被訪問器修改或插入。它還被用來在執(zhí)行設(shè)置時將改變處理器傳遞給訪問器,這允許改變處理器在屬性值改變的情況下發(fā)送改變。ImgFieldAccess這指定一個字段。大多數(shù)結(jié)構(gòu)字段是意義自明的。并非必須在客戶機上指定該描述。在服務(wù)器上,此字段可被用于反射。此標(biāo)記在服務(wù)器上被用來允許以低開銷引用特定字段。傳播該結(jié)構(gòu)的任何事物都有責(zé)任保持該標(biāo)記唯一。ImgFieldAccessors這指定一組字段訪問器。ImgClassDescription這描述一個類,指定獲取訪問器和設(shè)置訪問器。IImgAccessor此接口允許對特定字段的訪問。ImgVariant臨時存儲該數(shù)據(jù),并允許傳遞許多不同類型的數(shù)據(jù)。IImgTypeMaps此接口可由客戶機釋放。進(jìn)而,在注冊時被傳遞的所有訪問器接口將被釋放。IImgCommonData這是可被用來注冊類型映射的中心接口。此接口可被釋放,而類型映射注冊將仍保持有效。批處理接口其余子章節(jié)(即,對象查詢、對象命令和通知)以大量細(xì)節(jié)討論數(shù)據(jù)訪問接口。此節(jié)討論什么是對象以及客戶機如何獲取、設(shè)置和查詢對象??蛻魴C用來訪問這些對象的接口在以下代碼節(jié)選中示出。typedefenum{Serial,Parallel,Transactional,}EImgBatchSemantics;interfaceIImgAsyncResult;interfaceIImgCallCompletion;interfaceIImgBatch;interfaceIImgCommonData;interfaceIImgClientCollection;typedefenum{ActionCompleted,ActionPartiallyCompleted,ActionFailed,ActionDidNotExecute,ActionBatchDidNotExecute}EImgCompletionStatus;[local]interfaceIImgAsyncResult:IUnknown{void*GetCookie(void);voidSetCookie([in]void*cookie);HRESULTGetWaitHandle([out]HANDLE*pWaitHandle);BOOLCompletedSynchronously(void);BOOLDidComplete(void);}[local]interfaceIImgCallCompletion:IUnknown{HRESULTDone([in]IImgAsyncResult*pIResult);};[local]interfaceIImgBatch:IUnknown{HRESULTGetObjectData([in,string]constwchar_t*objectPath,[in]IImgTypeMap*pITypeMap,[in,out]void*pObject,[out,unique]ULONG*pulActionIndex);HRESULTSetObjectData([in,string]constwchar_t*objectPath,[in]IImgTypeMap*pITypeMap,[in]void*pObject,[out,unique]ULONG*pulActionIndex);HRESULTIssueCommandToObject([in,string]constwchar_t*objectPath,[in,string]constwchar_t*pType,[in,string]constwchar_t*pCommand,[in]ULONGcParams,[in,size_is(cParams)]ImgVariant*aimgVariant,[out,unique]ULONG*pulActionIndex);HRESULTQueryObjectData([in,string]constwchar_t*objectBase,[in,string]constwchar_t*objectClass,[in,string]constwchar_t*queryString,[in]IImgClientCollection*pIClientCollection,[out,unique]ULONG*pulActionIndex);HRESULTExecute(void);HRESULTBeginExecute([in,unique]IImgCallCompletion*pICallCompletion,[out,unique]IImgAsyncResult**ppIAsyncResult);HRESULTEndExecute([out]EImgCompletionStatus*pCompletion);////調(diào)用這些方法以從每個調(diào)用檢索額外的輸出信息。//HRESULTResultGetObjectData([in]ULONGulIndex,[out]EImgCompletionStatus*pCompletion);HRESULTResultSetObjectData([in]ULONGulIndex,[out]EImgCompletionStatus*pCompletion);HRESULTResultIssueCommand([in]ULONGulIndex,[out]EImgCompletionStatus*pCompletion,[out,unique]ImgReturnParams*pParams);HRESULTResultQueryObjectData([in]ULONGulIndex,[out]EImgCompletionStatus*pCompletion);HRESULTExtendedErrorResult([in]ULONGulIndex,[out]IErrorInfo**ppIErrorInfo);////取消批次上任何未決操作的方法。//HRESULTCancel([out]EImgCompletionStatus*pCompletion);};[local]interfaceIImgCommonData:IUnknown{HRESULTGetDataBatch([in]EImgBatchSemanticssemantics,[out]IImgBatch**ppIBatch);};[local]interfaceIImgClientCollection:IUnknown{HRESULTAllocateObject([out]void**ppObject);voidFreeObject([in]void*pObject);};此訪問接口公開新的概念,作為示例而非限制,這些新的概念包括·批處理接口(IImgBatch)·異步編程機制(IImgAsyncResult)·客戶機集合接口(IImgClientCollection)首先將抽象地討論其中每一個接口,然后將示出可能的調(diào)用序列的示例以使這些概念更加具體化。向數(shù)據(jù)訪問接口發(fā)布的所有動作都被批處理。批處理接口從對IImgCommonData::GetDataBatch()的調(diào)用返回,然后向批處理接口發(fā)布一組動作,最后該批次被執(zhí)行。如果調(diào)用者想要發(fā)布單個動作,則他們只要創(chuàng)建一個動作的批處理請求。在Execute方法被調(diào)用以前沒有任何動作被執(zhí)行。Execute可被同步或異步調(diào)用(取決于調(diào)用了Execute還是BeginExecute)。調(diào)用者可傳入完成接口,或可使用從IImgAsyncResult接口返回的等待句柄。規(guī)則是,如果調(diào)用者的確傳入了完成接口,則它們不能檢索等待句柄。調(diào)用者可通過cookie接口將相關(guān)聯(lián)的額外數(shù)據(jù)與調(diào)用相關(guān)聯(lián)。CDI保證在調(diào)用完成接口中將會調(diào)用Done方法以允許cookie在需要的情況下被釋放。調(diào)用者必須調(diào)用EndExecute調(diào)用來檢索批處理調(diào)用的結(jié)果。調(diào)用者可將批次作為串行、并行或事務(wù)式批次打開。非事務(wù)式批次可能會有部分成功返回,而事務(wù)式批次則不會。不幸的是,不是所有集合都支持事務(wù)(它們可能會與不支持事務(wù)的下級系統(tǒng)通信),并且如果該批次的任何動作與非事務(wù)式集合相交,則整個批次都將失敗。因此,根據(jù)一個實施例,事務(wù)式批處理主要可在系統(tǒng)內(nèi)部執(zhí)行,或僅在服務(wù)器版本已被肯定地標(biāo)識的情況下被執(zhí)行。對于一些如“暫停所有打印機”等可批處理的動作而言,進(jìn)行事務(wù)式處理是沒有意義的,因為在一個隊列未能暫停的情況下,人們會寧愿使一半隊列被暫停而不是沒有一個隊列被暫停。如果批次的語義是串行的,則可保證該批次中的動作被依次執(zhí)行。如果批次的語義是并行的,則系統(tǒng)可在有充分資源的情況下,或在這是最優(yōu)方案的情況下并行地執(zhí)行動作。這意味著對于并行批次語義而言,任何動作可按任何順序失敗。事務(wù)式批次也蘊含順序語義。批次中的每個都作返回遞增的索引。調(diào)用者如果無需檢索批次調(diào)用(可以是事務(wù)式批次,且該批次的狀態(tài)是該動作的狀態(tài))的結(jié)果則它們可以忽略索引。每個調(diào)用的結(jié)果可通過調(diào)用批處理接口中對應(yīng)的“Result”方法來檢索。如果調(diào)用報告出錯,則可從批次返回經(jīng)擴展的出錯信息。同步和異步形式的執(zhí)行除了在異步情形中,返回狀態(tài)是從EndExecute調(diào)用返回以外其它都是相同的。因為批處理命令可并行執(zhí)行,所以批次可以有部分失敗結(jié)果。因此在調(diào)用者期望的情況下,可查詢每個索引來準(zhǔn)確地確定哪個調(diào)用失敗,以及失敗的原因是什么。根據(jù)一個實施例,批處理接口上的方法概述如下·GetObjectData-此方法使用給定類型映射和調(diào)用者所指定的對象從給定對象名檢索數(shù)據(jù)。·SetObjectData-此方法使用要進(jìn)行寫的給定類型映射(客戶機集合和服務(wù)器集合之間的訪問器被顛倒)和要從其檢索數(shù)據(jù)的對象來將數(shù)據(jù)寫到給定對象。注意,如果數(shù)據(jù)正被發(fā)送到遠(yuǎn)程目的地,則這些內(nèi)容將被提前從對象復(fù)制出來。如果是對本地對象設(shè)置該數(shù)據(jù),則這些內(nèi)容將在稍后當(dāng)實際的設(shè)置發(fā)生時被復(fù)制出來?!ueryObjectData-此方法發(fā)布對某個對象類的查詢。查詢將在以下更加詳細(xì)地討論。除了將從集合分配許多對象而不只是一個對象以滿足查詢這一點以外,查詢在概念上非常類似于Get命令?!ssueCommandToObject-此方法向?qū)ο蟀l(fā)布命令。命令將在以下更加詳細(xì)地討論。命令是向給定對象上的特定類型發(fā)布的。命令本身是unicode串,它接收輸入?yún)?shù)的有序列表。輸出參數(shù)可由調(diào)用者通過ResultIssueCommand調(diào)用檢索?!xecute-此方法使迄今要被批處理的的所有命令被執(zhí)行?!ancel-此方法取消在Execute調(diào)用以后目前正在進(jìn)行中的任何動作。它還在該調(diào)用被執(zhí)行以前刷新來自批處理接口的任何命令。批處理接口只可在Cancel調(diào)用返回以后,或在同步Execute調(diào)用完成或異步EndExecute調(diào)用返回以后被重用。圖6示出批次調(diào)用命令的圖示。此例假定IImgDataBatch接口構(gòu)建要被執(zhí)行的命令的列表。查詢、命令和通知在后續(xù)章節(jié)中被詳細(xì)覆蓋。由此,以下示出獲取對象的狀態(tài)、然后改變對象的名稱和注釋、并再次應(yīng)用這些改變的示例性代碼片段。該代碼是以異步回調(diào)形式編寫以說明異步批處理接口,但是實際上它并不需要此復(fù)雜性。structClientPrinter{ULONGStatus;BSTRName;BSTRLocation;BSTRComment;ClientPrinter(void){ZeroMemory(this,sizeof(*this));}~ClientPrinter(void){SysFreeString(Name);SysFreeString(Location);SysFreeString(Comment);}};IMG_ATTR_TABLE_BEGIN(ClientPrinter,TypeMap)Type("Micrsoft.Printer.Basic"),Field(IMG_ATTR_FIELD(Status)),Field(IMG_ATTR_FIELD(Name)),Field(IMG_ATTR_FIELD(Location)),Field(IMG_ATTR_FIELD(Comment)),IMG_ATTR_TABLE_ENDclassOperations:publicIImgCallCompletion{public:Operations(INIImgDataBatch*pIBatch,INIImgTypeMap*pITypeMap){m_pIBatch=pIBatch;m_pITypeMap=pITypeMap;m_pIBatch->AddRef();m_pITypeMap->AddRef();}-Operations(void){m_pIBatch->Release();m_pITypeMap->Release();}////在此插入你最喜歡的IUknown實現(xiàn)。//voidStartOperation(Void){////通常我們將通過查詢獲取此對象規(guī)范名稱。//m_pIBatch->GetObjectData(L"{4810742c-c8d9-44c3-81bb-c3ff5f83d762}\"L"{f5ddca93-06f9-40c3-8c7f-a61c3e390fae}",m_pITypeMap,&m_clientPrinter,NULL);////我們不需要異步結(jié)果,我們只需將我們自己的接口傳入到批次中。//m_pIBatch->BeginExecute(this,NULL);}////IImgCallCompletion實現(xiàn)。//STDMETHODIMPDone(INIImgAsyncResult*pIResult){m_pIBatch->EndExecute();////改變名稱和注釋。//SysFreeString(m_clientPrinter.Name);SysFreeString(m_clientPrinter.Comment);m_clientPrinter.Name=SysAllocString(L"NewName");m_clientPrinter.Comment=SysAllocString(L"Thereisacommenthere.");////應(yīng)用該改變,這次是同步地。//m_pIBatch->SetObjectData(L"{4810742c-c8d9-44c3-81bb-c3ff5f83d762}\"L"{f5ddca93-06f9-40c3-8c7f-a61c3e390fae}",m_pITypeMap,&m_clientPrinter,NULL);m_pIBatch->Execute();}private:IImgDataBatch*m_pIBatch;IImgTypeMap*m_pITypeMap;ClientPrinterm_clientPrinter;}intmain(void){IImgCommonData*pICDI=NULL;IImgTypeMap*pITypeMap=NULL;CoCreateInstance(CLSID_ImgCommonData,NULL,CLSCTX_INPROC_SERVER,IID_IImgCommonData,Reintpret_cast<void**>(&pICDI));Img::iatl::RegisterTypeMap(pICDI,IMG_ATTR_TABLE(ClientPrinter,TypeMap),&pITypeMap);IImgDataBatch*pIBatch=NULL;pICD->GetDataBatch(NonTransactional,&pIBatch);Operations*pOperations=newOperations(pIBatch,pITypeMap);pOperations->StartOperation();////休眠10秒以允許進(jìn)行獲取和設(shè)置。//Sleep(10000);pOperations->Release();pIBatch->Release();pICDI->Release();pITypeMap->Release();return0;}對象查詢這一節(jié)描述對象查詢。由IDataAccessBatch公開的接口在以下示出。[local]interfaceIImgBatch:IUnknown{HRESULTQueryObjectData([in,string]constwchar_t*objectPath,[in,string]constwchar_t*objectBase,[in,string]constwchar_t*objectBaseClass,[in,string]constwchar_t*desiredObjectClass,[in,string]constwchar_t*queryString,[in]IImgClientCollection*pIClientCollection,[out,unique]ULONG*pulActionIndex);HRESULTResultQueryObjectData([in]ULONGulIndex,[out]EImgCompletionStatus*pCompletion);};typeMap和clientCollection參數(shù)已經(jīng)討論過。queryString參數(shù)控制查詢。如果它是null,則該查詢請求如查詢基所指定的給定類型的所有對象。如果它不為null,則它為查詢指定過濾器。查詢包含查詢基、查詢類和查詢串。查詢串將在稍后討論。查詢基是查詢的根對象,即,它是可認(rèn)為其它對象存在于其下的那個對象(作業(yè)枚舉的查詢基可以是打印機或服務(wù)器對象)。查詢基關(guān)系通常不是分層結(jié)構(gòu),而是關(guān)系型的(即,不能枚舉查詢基兩級以下的對象)。但是,和嚴(yán)格的分層結(jié)構(gòu)不同,對象可被定位在許多不同的查詢基下。這反映了底層存儲是關(guān)系型的這一事實。支持查詢基的主要原因是允許查詢的基于下級枚舉的實現(xiàn)能很容易地找到對應(yīng)于該枚舉的根對象。但是,查詢基使得對上級情形的查詢的語法分析復(fù)雜化。下表中示出查詢和類型的示例性列表。注意,集合中的對象可能并不使用集合的編程名稱。它們應(yīng)當(dāng)使用友好名稱的名稱解析機制,然后內(nèi)部地使用數(shù)字的對象名稱來引用該對象。允許使用編程名稱來進(jìn)行查詢來指定集合,因為串更加可能是由人類裝配而成。注意,不要求遠(yuǎn)程集合為對本地機器的查詢返回任何對象。要它們查詢所有服務(wù)器效率過于低下。查詢串是指定給定對象必須具有的屬性的過濾器。字段采取以下形式Programmatic.Type.Name.Version:FieldName.將來的查詢可被允許訪問嵌入在數(shù)據(jù)中的XML文檔內(nèi)的數(shù)據(jù)。這些查詢將采取以下形式Programatic.Type.Name.Version:FieldName\Node\Node\Property.下表中示出有效運算符及其優(yōu)先級。只可對照常量來比較字段。以下是有效的常量·任何整數(shù)。整數(shù)可用十進(jìn)制或十六進(jìn)制形式表達(dá)?!と魏胃↑c數(shù)?!と魏我砸栐谧置嫔蟿澖绲拇?。如果引號必須是該串的一個部分,則使用BASIC樣式的“”。下表中示出有效的查詢。為簡化一些經(jīng)常被訪問的對象的語義,可以有允許可與下級服務(wù)器更容易地進(jìn)行相互操作的定義良好的查詢基。這些將包括——·打印隊列查詢-查詢基應(yīng)為包含該打印隊列的服務(wù)器對象?!ぷ鳂I(yè)對象查詢-查詢基應(yīng)為包含這些作業(yè)的隊列或服務(wù)器對象。根據(jù)一個實施例,以下約束適用于查詢·如果查詢對照數(shù)字類型(整數(shù)或者浮點)比較字段,則實際的字段必須是數(shù)字的(32位整數(shù)、64位整數(shù)或雙精度浮點)?!と绻樵儗φ沾愋捅容^字段,并且比較運算符不是CONTAINS,則唯一有效的字段類型是BSTR或IImgImutableString?!ONTAINS運算符僅對串類型生效。對于單值的串,它等于檢查相等性。對于規(guī)范名稱,它等于檢查路徑是相同的。對于多串,它等于檢查多串中的任何串是否相等。對于多值名稱,它等于檢查由多值名稱中的任何規(guī)范名稱所表達(dá)的任何路徑是否等于CONTAINS運算符所引用的串?!ぐ次慌c運算僅適用于整數(shù)類型。為使此討論更加具體化,以下代碼節(jié)選給出一個示例。此例查詢一組打印對象,然后枚舉它們。此例使用IAsyncResult接口的可等待形式。同樣,在此情形中這不是必須的,但它示出了該接口的另一個用法。注意,我們使用模板庫中為調(diào)用者自動構(gòu)建IImgClientCollection和枚舉器的特征。為簡略起見省略了出錯處理。structClientJob{ULONGStatus;BSTRDocumentName;ClientJob(void){ZeroMemory(this,sizeof(*this));}-ClientJob(void){SysFreeString(DocumentName);}};IMG_ATTR_TABLE_BEGIN(ClientJob,TypeMap)Type("Micrsoft.Job.Basic"),Field(IMG_ATTR_FIELD(Status)),Field(IMG_ATTR_FIELD(DocumentName)),IMG_ATTR_TABLE_ENDintmain(void){IImgCommonData*pICDI=NULL,IImgTypeMap*pITypeMap=NULL;CoCreateInstance(CLSID_ImgCommonData,NULL,CLSCTX_INPROC_SERVER,IID_IImgCommonData,reinterpret_cast<void**>(&pICDI));Img::iatl::RegisterTypeMap(pICDI,IMG_ATTR_TABLE(ClientJob,TypeMap),&pITypeMap);Img::iatl::TClientCollection<ClientJob>*pClientCollection=newImg::iatl::TClientCollection<ClientJob>();IImgDataBatch*pIBatch=NULL;pICD->GetDataBatch(NonTransactional,&pIBatch);////查詢本地機器上屬于ToeKneeHeart且長度超過120kB的所有作業(yè)。//pIBatch->QueryObjectData(NULL,L"Microsoft.Job",L"Microsoft.Job.Basic:UserName=\"ToeKneeHeart\"AND"L"Microsoft.Job.Basic:Size>120000",pClientCollection,NULL);IImgAsyncResult*pIAysncResult=NULL;pIBatch->BeginExecute(NULL,&pIAsyncResult);HANDLEhEvent=NULL;////獲取可等待的句柄,在數(shù)據(jù)就緒時它將被通知。//pIAsyncResult->GetWaitHandle(&hEvent);////在查詢未決時可做任何想做的事。//WaitForSingleObject(hEvent,INFINITE);EImgBatchCompletionStatusstatus;pIBatch->EndExecute(&status);Img::iatl::TClientCollection<ClientJob>::Iteratori(pCollection);For(i.Init();!i.Done();i.Next()){ClientJob*pClientJob=i.Current();wprintf(L"Document:%s-Status:%d\n",pClientJob->DocumentName,pClientJob->Status);}pIAsyncResult->Release();pClientCollection->Release();pIBatch->Release();pICDI->Release();pITypeMap->Release();return0;}對象命令和對對象集合的查詢一樣,可向給定對象發(fā)布命令。對對象的命令被綁定到類型,包括該對象可具有的來自其它集合的任何嵌入類型。這允許在每實例的基礎(chǔ)上擴展對象的命令集。根據(jù)一個實施例,命令具有以下屬性·命令永遠(yuǎn)不被高速緩存,而數(shù)據(jù)可被高速緩存?!っ羁沙绞‘惓O蛘{(diào)用者返回參數(shù)?!っ罹哂幸唤M固定的有序輸入和輸出參數(shù)。命令不能被重載或擴展。命令的語義在系統(tǒng)的新版本上永遠(yuǎn)不能改變。(命令可能會過時并且最終可能停止支持。)命令將被用于對象構(gòu)造和對象刪除。對于對象刪除,定義了預(yù)定義的類型和方法——“Microsoft.GenericObject.1”命令“Delete”。刪除命令不需要參數(shù)也不返回參數(shù)。所有可刪除的對象都被要求公開此命令。所有嵌入的對象也被要求公開此命令。當(dāng)嵌入對象的包含對象被刪除時,它將要求所有嵌入對象將它們自己刪除。所有可保護(hù)對象將被要求公開的另一個命令是“Microsoft.GenericObject.1”命令“AccessCheck”,此命令取單個參數(shù)——許可對象,并返回真或假。此命令被嵌入類型用來確保在它們被通過自己的集合訪問時,它們強制執(zhí)行了和包含對象相同的安全語義。從命令調(diào)用結(jié)果返回的參數(shù)的生命期和批次的生命期是一樣的。當(dāng)批次被釋放、取消,或者對該批次執(zhí)行了另一個動作,則命令參數(shù)將被清除。最后,以下給出命令接口的示例性用法。此例從已被發(fā)現(xiàn)的打印隊列請求流對象。intMain(void){IImgCommonData*pICDI=NULL;CoCreateInstance(CLSID_ImgCommonData,NULL,CLSCTX_INPROC_SERVER,IImg_ICommonData,reinterpret_cast<void**>(&pICDI));pICDI->GetDataBatch(NonTransactional,&pIBatch);ULONGulIndex=0;ImgReturnParamsparams;EImgCompletionStatuscompletion;pIBatch->IssueCommandToObject(L"{4810742c-c8d9-44c3-81bb-c3ff5f83d762}\"L"{f5ddca93-06f9-40c3-8c7f-a61c3e390fae}",L"Microsoft.Printer.Basic",L"GetJobStream",O,NULL,&ulIndex);pIBatch->Execute();pIBatch->ResultIssueCommand(ulIndex,&completion,&params);////檢查作業(yè)參數(shù)和類型//if(completion==ActionCompleted&&params.cParams==1&&params.aParams.type==CustomTypeJobStream){IJobStream*pIJobStream=(IJobStream)params.aParams.pOtherVal;pIJobStream->AddRef();////對該作業(yè)流執(zhí)行某些動作//pIJobStream->Release();}pIBatch->Release();////現(xiàn)在Params將指向無用單元//pICDI->Release();return0;}通知通知也可從對象、對象類、服務(wù)器或集合接收。此接口也被從客戶機批處理。該接口如下所示。typedefenum{NotifyAddNewObject,NotifyAddMatchedFilter}EImgNotifyAddReason;typedefenum{NotifyRemoveDeletedObject,NotifyRemoveDoesNotMatchFilter}EImgNotifyRemoveReason;typedefenum{NotifyUpdatePopulate,NotifyUpdate}EImgNotifyUpdateReason;[local]interfaceIImgBatch:IUnknown{HRESULTRegisterNotificationCollection([in,string]constwchar_t*objectBase,[in,string]constwchar_t*objectClass,[in,string]constwchar_t*queryString,[in]IImgNotificationCollection*INotificationCollection,[in]IImgTypeMap*pITypeMap,[in,unique]IImgCallCompletion*pICallCompletion,[out]ULONG*pulActionIndex);HRESULTResultNotificationCollection([in]ULONGulIndex,[out]EImgCompletionStatus*pCompletion,[out]IImgNotificationChannel**ppIChannel);};[local]interfaceIImgNotificationChannel:IImgAsyncResult{HRESULTPopulate(void);HRESULTUpdate(void);}[local]interfaceIImgNotificationObject:IUnknown{HRESULTBeginNotifyChanges([in]EImgNotifyUpdateReasonreason);HRESULTEndNotifyChanges(void);HRESULTGetRealObjectAddress([out]void**ppObject);};[local]interfaceIImgNotificationCollection:IUnknown{HRESULTAddObject([in]EImgNotifyAddReasonreason,[out]IImgNotificationObject**ppIObject);voidRemoveObject([in]EImgNotifyRemoveReasonreason,[in]IImgNotificationObject*pIObject);};此接口公開若干新的概念,作為示例而非限制,其中包括了通知集合、通知對象、通知過濾器、以及通知通道。此接口用另外兩個動作RegisterNotificationCollection和ResultNotificationCollection來擴展批處理接口。通知集合是具有略為豐富的語義的客戶機集合。它是同類客戶機對象的集合。每個對象都可用一個類型映射來描述。當(dāng)發(fā)生針對特定對象改變的通知時,或者如果一對象被添加,則該對象被檢索,然后被填充。當(dāng)對象的新數(shù)據(jù)已被放置于其中時,該對象上的EndNotifyChanges方法被調(diào)用以允許一旦對象被更新,實現(xiàn)者即可執(zhí)行任何必須的處理。由調(diào)用者指定的通知集合將總被串行地更新(即,它可由多個線程調(diào)用,但是每次只有一個線程將調(diào)用它)。通知集合只有在對通道進(jìn)行Populate(填充)或Update(更新)調(diào)用時才會被更新。因此,如果調(diào)用者正在對其對象執(zhí)行多線程的訪問,則調(diào)用者可通過在Populate或Update調(diào)用周圍放置適當(dāng)?shù)逆i來保護(hù)其對象。如果調(diào)用者對通知指定了回調(diào),則每次只有單個線程被保證在回調(diào)中執(zhí)行。通知按以下方式工作。當(dāng)對通道進(jìn)行Populate調(diào)用時,對象將通過Add(添加)方法被從指定的集合分配。然后將用BeginNotifyChanges調(diào)用來調(diào)用這些對象,而在此時這是更新周期還是填充周期的信息將會被傳入對象中。然后,通過通知通道接收到通知。如果調(diào)用者指定了回調(diào),則當(dāng)接收到新的更新時(或當(dāng)該通道出錯時)回調(diào)將被調(diào)用。如果調(diào)用者沒有指定回調(diào),則將會有等待句柄可用,或可用IsCompleted方法輪詢該通道。通知是由子系統(tǒng)接收的,但在對通道調(diào)用Update方法以前不被應(yīng)用于客戶機對象。如果通道由于某個原因而中斷,則更新將返回適當(dāng)?shù)腻e誤。在對Update的調(diào)用期間,將用服務(wù)器上有所改變的任何屬性更新客戶機對象。如果在服務(wù)器上創(chuàng)建了任何新的對象,或如果它們?nèi)缃衿ヅ渫ㄖ^濾器,則集合將接收對Add方法的調(diào)用,并將被告知通知的原因是該對象現(xiàn)在匹配過濾器,還是該對象是新的。類似地,如果任何對象現(xiàn)在的確匹配過濾器,或如果它們已被刪除,則集合上的Remove(移除)方法被調(diào)用。對象是通過對其屬性的直接調(diào)用來更新的。更新將由對BeginNotifyChanges和EndNotifyChanges方法的調(diào)用括在一起。當(dāng)調(diào)用者想要停止接收通知時,它們釋放它們所接收的INotificationChannel接口。以下示出從集合中的所有本地對象接收對應(yīng)于兩個字段的通知的示例性代碼。此示例性代碼接收本地集合中所有打印機的Status(狀態(tài))和Name(名稱)字段的改變。假定查詢的結(jié)果是在屏幕上更新打印機。為可讀性起見,出錯處理被省略。classMyNotificationObject:publicIImgNotificationObject{////在此處插入您最喜歡的IUnknown實現(xiàn)。//STDMETHODIMPBeginNotifyChanges(INEImgNotifyUpdateReasonreason){returnS_OK;}STDMETHODIMPEndNotifyChanges(void){////將我的對象狀態(tài)寫出到屏幕。//returnS_OK;}STDMETHODIMPGetRealObjectAddress(OUTvoid**ppvObject){*ppvObject=this;returnS_OK;}IMG_ATTR_TABLE_FRIEND(MyNotificationObject,TypeMap);private:BSTRName;ULONGStatus;};IMG_ATTR_TABLE_BEGIN(ClientJob,TypeMap)Type("Micrsoft.Printer.Basic"),Field(IMG_ATTR_FIELD(Name)),Field(IMG_ATTR_FIELD(Status)),IMG_ATTR_TABLE_ENDclassMyNotificationCollection:publicIImgNotificationCollection{public:////在此處插入您最喜歡的IUnknown實現(xiàn)。//STDMETHODIMPAddObject(INEImgNotifyAddReasonaddReason,OUTIImgNotificationObject**ppIObject){MyNotificationObject*pNotifyObject=newMyNotificationObject;////第一次在UI中顯示通知對象//*ppIObhect=pNotifyObject;returnS_OK;}STDMETHODIMP_(void)Remove(INEImgNotifyRemoveReasonremoteReason,INIImgNotificationObject*pINotifyObject){////將通知對象從UI遠(yuǎn)程化。并移除對其的任何引用。//pINotifyObject->Release();}}intmain(void){IImgCommonData*pICDI=NULL;IImgTypeMap*pITypeMap=NULL;ImgGetDataInterface(&pICDI);Img::iatl::RegisterTypeMap(pICDI,IMG_ATTR_TABLE(MyNotificationObject,TypeMap),&pITypeMap);IImgDataBatch*pIBatch=NULL;MyNotificationCollection*pMyCollection=newMyNotificationCollection();pICDI->GetDataBatch(NonTransactional,&pIBatch);ULONGulIndex=0;////找出關(guān)于所有本地打印機的信息,不使用過濾器。//pIBatch->RegisterNotificationCollection(NULL,"Microsoft.Printers",NULL,pMyCollection,pITypeMap,NULL,&ulIndex);pIBatch->Execute();IImgNotificationChannel*pIChannel=NULL;EImgCompletionStatusstatus;HANDLEhEvent=NULL;pIBatch->ResultNotificationCollection(uLIndex,&status,&pIChannel);////從通知通道獲取等待句柄。//pIChannel->GetWaitHandle(&hEvent);////填充信道,在這個時間點集合將獲取填充信道所需的所有回調(diào)。//pIChannel->Populate();do{////任何時候一有改變這就會被通知。//WaitForSingleObject(hEvent,INFINITE);////我們知道在我們調(diào)用更新以前通知集合和對象不會被觸及。在此調(diào)用上任何錯誤都將被返回。//pIChannel->Update();}while(1);pIChannel->Release();pMyCollection->Release();pIBatch->Release();pICDI->Release();pITypeMap->Release();return0;}客戶機集合CDI接口的一個方面,即填充客戶機集合和客戶機對象而不是將數(shù)據(jù)寫入某種中間數(shù)據(jù)對象并傳播該數(shù)據(jù)集這一選擇帶有一些優(yōu)點。例如,這樣做允許以非常相似的方式對待通知和數(shù)據(jù)填充。從客戶機的角度來看,這意味著可非常容易地在這兩種情形之間重用客戶機對象。此外,這樣做允許客戶機代碼變得極為高效。特別地,一旦數(shù)據(jù)被集合到客戶機對象中,它即可作為結(jié)構(gòu)內(nèi)的偏移量被本機地引用。如果數(shù)據(jù)被存儲在中間集合中,則或是客戶機不得不進(jìn)而將該數(shù)據(jù)復(fù)制到某些客戶機對象中以操縱該數(shù)據(jù),或是每次都必須從集合檢索該數(shù)據(jù)。此外,填充客戶機集合和客戶機對象將客戶機代碼中的失敗條件限制于該數(shù)據(jù)被填充的時候,而不是從集合復(fù)制該數(shù)據(jù)的時候。這就有實質(zhì)上降低客戶機代碼復(fù)雜性的潛在可能。當(dāng)使用中間集合時,只要集合中的數(shù)據(jù)被訪問,就有失敗的可能。此外,填充客戶機集合和客戶機對象允許使用多種中間集合。本質(zhì)上,此機制封裝完全靈活的構(gòu)建器模式。這意味著通用的“客戶機”可動態(tài)地構(gòu)建類型映射,并將其映射到其所希望的任何一種中間集合。這可被用來為托管數(shù)據(jù)提供程序構(gòu)建數(shù)據(jù)集對象。或者,它可被用來構(gòu)建數(shù)據(jù)的XML視圖。這可在沒有因中間數(shù)據(jù)集的插入所引起的任何保真度或性能損失的情況下實現(xiàn)。此外,一相關(guān)屬性是填充客戶機集合和客戶機對象允許客戶機集合實際上成為以可被容易地遠(yuǎn)程化的形式準(zhǔn)備數(shù)據(jù)的訪問適配器。但是,在消極方面,它可能強制客戶機對象為它想要檢索的每個屬性公開訪問器。動態(tài)類型映射所示出并描述的實施例可被用來解決當(dāng)用戶想要有一個對象實例,但是想要能夠根據(jù)調(diào)用條件從服務(wù)器對象動態(tài)地檢索不同的字段時的情況。有兩種可能發(fā)生此問題的情形——其一是,當(dāng)有具有許多屬性的具體對象,但調(diào)用者想要在給定調(diào)用中傳播的實際屬性是動態(tài)的時候;以及,另一情形是當(dāng)調(diào)用者真的想要完全動態(tài)地處理數(shù)據(jù)的時候。在所示出并描述的體系結(jié)構(gòu)中,每種情形都具有解決方案。為解決第一個問題,所示出并描述的實施例使用與每個屬性相關(guān)聯(lián)的標(biāo)記來從該類構(gòu)建子集動態(tài)類型映射。這些標(biāo)記也可被指定為模板庫的一個部分。模板庫將檢索只匹配所指定的標(biāo)記的部分類型映射。此解決方案在以下代碼節(jié)選中示出。structClientPrinter{enumFieldTags{Status,Name,Location,Comment};ULONGStatus;BSTRName;BSTRLocation;BSTRComment;};IMG_ATTR_TABLE_BEGIN(ClientPrinter,TypeMap)Type("Micrsoft.Printer.Basic"),Field(IMG_ATTR_FIELD(Status),ClientPrinter.FieldTags.Status),Field(IMG_ATTR_FIELD(Name),ClientPrinter.FieldTags.Name),Field(IMG_ATTR_FIELD(Location),ClientPrinter.FieldTags.Location),Field(IMG_ATTR_FIELD(Comment),ClientPrinter.FieldTags.Comment),IMG_ATTR_TABLE_ENDvoidInitializeTypeMap(Void){IImgCommonData*pICDI=NULL;IImgTypeMap*pITypeMap=NULL;int_ptrTags[]={ClientPrinter.FieldTags.Name,ClientPrinter.FieldTags.Comment};ImgGetDataInterface(&pICD);Img::iatl::RegisterTypeMap(pICDI,IMG_ATTR_TABLE(ClientPrinter,TypeMap),tags,&pITypeMap);////對類型映射進(jìn)行操作//pICDI->Release();pITypeMap->Release();}允許從遠(yuǎn)程服務(wù)器檢索完全是運行時確定的一組完全隨機的屬性還可通過類型映射接口來實現(xiàn)。但是在此情形中,不能僅令一組屬性綁定到類。在此情形中,實際上起作用的是低級類型映射接口的能力和靈活性。在此情形中,調(diào)用者可利用每個接口也是一對象實例這一事實,并可直接使用Variant類型。此概念在圖7中示出。圖中,每個接口實際上指向一個對象而不是靜態(tài)方法或字段。每個對象維護(hù)關(guān)于它應(yīng)如何操縱最終目標(biāo)對象的某種狀態(tài)。在此例中,它維護(hù)目標(biāo)對象所維護(hù)的對象數(shù)組中的索引。目標(biāo)對象的數(shù)組大小是可變的,且委托對象和類型映射可被動態(tài)構(gòu)建。因此,此機制允許調(diào)用者綁定到任何源對象,并允許即時創(chuàng)建任何源對象。在所示出并描述的實施例中,此機制實際上完全是通用的。沒有特定理由讓這些接口不能參與構(gòu)建XML文檔、創(chuàng)建數(shù)據(jù)集或?qū)?shù)據(jù)寫到屏幕。它還可被用來以任何形式構(gòu)建對象集合。這在橋接到長角系統(tǒng)(longhorn)API或其它數(shù)據(jù)訪問API時非常有用。以下示出實現(xiàn)此方案的代碼,包括通過批處理接口訪問一個對象(出錯處理被省略)。classDestinationObject{public:DestinationObject(intarraySize){m_apVariant=newImgVariant[arraySize];m_apSize=arraySize;}~DestinationObject(void){for(inti=0;I<m_apSize;i++){ImgVariantClear(&m_apVariant[i]);}delete[]m_apVariant;}private:friendclassObjectAccessor;ImgVariant*m_apVariant;intm_apSize;};classObjectAccessor:publicIImgAccessor{public:ObjectAccessor(Intindex,IImgCommonData*pICDI):m_index(index),m_pICDI(pICDI){m_pICDI->AddRef();}~ObjectAccessor(){m_pICDI->Release();}////首選的標(biāo)準(zhǔn)IUnknown實現(xiàn)//////IImgAccessor//STDMETHODIMPFunction(INvoid*pObject,INOUTImgVariant*pData,INOUTImgExtraCopyData*pExtra){DestinationObject*object=reinterpret_cast<DestinationObject*>(pObject);returnm_pICDI->VariantCopy(&object->m_apVariant[m_index]);}private:intm_index;IImgCommonData*m_pICDI;};intmain(void){IImgCommonData*pICD=NULL;CoCreateInstance(CLSID_ImgCommonData,NULL,CLSCTX_INPROC_SERVER,IImgCommonData,reinterpret_cast<void**>(pICDI));////構(gòu)建一種訪問Microsoft.Printer.Basic:Location、注釋和狀態(tài)的機制。//ImgFieldAccessorAccessors[]={{"Microsoft.Printer.Basic","Location",ImgVariantType,newObjectAccessor(0,pICDI)},{"Microsoft.Printer.Basic","Comment",ImgVariantType,newObjectAccessor(1,pICDI)},{"Microsoft.Printer.Basic","Status",ImgVariantType,newObjectAccessor(2,pCDI)},};ImgClassDescriptionClassDescription={{COUNTOF(Accessors),Accessors},{0},{0},};IImgTypeMap*pITypeMap=NULL;IImgBatch*pIBatch=NULL;ImgGetDataInterface(&pICD);pICD->RegisterTypeMap(&ClassDescription,&pITypeMap);////現(xiàn)在我們可對目標(biāo)對象使用該類型映射//pICD->GetBatch(&pIBatch);DestinationObjectdestObj(3);pIBatch->GetObjectData(L"{8e677748-cd3e-440f-ae30-eecec8c8017f}\62756091-4744-4896-b077-73ad0974d923pITypeMap,&destObj,NULL);pIBatch->Execute();////現(xiàn)在...destObj中將有位置、狀態(tài)和注釋。//pICD->Release();pITypeMap->Release();pIBatch->Release();Accessors->pIAccessor->Release();Accessors[1]->pIAccessor->Release();Accessors[2]->pIAccessor->Release();return0;}屬性模板庫和繼承模板庫值得關(guān)注的方面之一是它支持對象之間的繼承(包括多繼承)。這在客戶機上沒有像在服務(wù)器中那么有用。在服務(wù)器上,這允許公共功能以及對應(yīng)的字段和方法被存儲在基類中,并在需要的情況下被帶入派生類中。除了支持繼承以外,該庫還正確地處理虛方法。即,可在基類類型映射中引用基類中的虛方法,然后在調(diào)用派生類型映射中將正確地調(diào)用派生類。以下代碼節(jié)選中示出一組起效的類型的示例。此代碼僅示出諸類的結(jié)構(gòu)——為簡略起見任何實現(xiàn)均被省略。structTBaseClass{BSTRName(void);HRESULTset_Name(INBSTRbstrName);virtualULONGcJobs(void);virtualvoidset_cJobs(INULONGcJobs);ULONGm_Status;};IMG_ATTR_TABLE_BEGIN(TBaseClass,Img::iatl::TypeMap)Type(L"BaseClass"),Field(IMG_ATTR_FIELD(m_Status),L"Status"),Field(IMG_ATTR_METHOD(TBaseClass::Name),gGet),Field(IMG_ATTR_METHOD(TBaseClass::set_Name),L"Name",gSet),Field(IMG_ATTR_METHOD(TBaseClass::cJobs),gGet),Field(IMG_ATTR_METHOD(TBaseClass::set_cJobs),L"cJobs",gSet),IMG_ATTR_TABLE_ENDclassTBaseClass2{public:IMG_ATTR_TABLE_FRIEND(TBaseClass2,Img::iatl::TypeMap);protected:BSTRget_Location(void);voidset_Location(INBSTRlocation);virtualHRESULTget_Comment(INOUTBSTR*pComment)=0;virtualHRESULTset_Comment(INBSTRComment)=0;private:ULONGExtraStatus;};IMG_ATTR_TABLE_BEGIN(TBaseClass2,Img::iatl::TypeMap)Type(L"BaseClass2"),Field(IMG_ATTR_FIELD(ExtraStatus)),Field(IMG_ATTR_METHOD(TBaseClass2::get_Location),L"Location",gGet),Field(IMG_ATTR_METHOD(TBaseClass2::set_Location),L"Location",gSet),Field(IMG_ATTR_METHOD(TBaseClass2::get_Comment),L"Comment",gGet),Field(IMG_ATTR_METHOD(TBaseClass2::set_Comment),L"Comment",gSet),IMG_ATTR_TABLE_ENDclassTDerived:publicTBaseClass,publicTBaseClass2{public:IMG_ATTR_TABLE_FRIEND(TDerived,Img::iatl::TypeMap);////覆蓋set_cJobs的實現(xiàn)。//voidset_cJobs(INULONGcJobs);protected:////實現(xiàn)獲取和設(shè)置的注釋。//HRESULTget_Comment(INOUTBSTR*pComment);virtualHRESULTset_Comment(INBSTRComment);ULONGChainedJobs;ULONGAttributes;};IMG_ATTR_TABLE_BEGIN(TDerived,Img::iatl::TypeMap)Type(L"Derived"),Field(IMG_ATTR_FIELD(ChainedJobs)),Inherits(IMG_ATTR_INHERIT_TABLE(TBaseClass)),Field(IMG_ATTR_FIELD(Attributes)),Inherits(IMG_ATTR_INHERIT_TABLE(TBaseClass2)),IMG_ATTR_TABLE_END在此例中,派生類覆蓋一個虛方法,并實現(xiàn)兩個純方法。其它所有字段和方法被從基類中帶入。即使表的定義實際上是從基類的中所定義的表帶入的,派生類的方法仍被調(diào)用。派生表帶入了基類表的定義,其表中有“Inherits”(繼承)字段。對基類和基類表的任何擴展將被立即反映在派生類的表中。因此,可示出這些表實現(xiàn)真正的多繼承。游標(biāo)游標(biāo)是允許調(diào)用者以一次一塊而不是以單個請求的形式從服務(wù)器檢索數(shù)據(jù)的接口。這在服務(wù)器上有大量對象需被枚舉時特別有用。這減少了一次調(diào)用中必須通過網(wǎng)絡(luò)返回的數(shù)據(jù)量,并且它縮減了服務(wù)器方的工作集。對于非常大的對象集合,它還可允許客戶機避免將所有對象存儲在存儲器中。相反,客戶機可在表中維護(hù)游標(biāo),并按需檢索更多的行。在此特定實現(xiàn)示例中,當(dāng)前沒有在CDI中實現(xiàn)游標(biāo),這是由于以下原因·服務(wù)器上所維護(hù)的對象個數(shù)與典型的數(shù)據(jù)庫中所存儲的對象個數(shù)不是相同的數(shù)量級??蛻魴C沒有足夠存儲器來存儲其數(shù)據(jù)副本是非常不可能的?!し?wù)器上的許多對象必須是活動的,因為大多數(shù)隊列將會接收作業(yè)。因此,與在數(shù)據(jù)庫中相比,工作集不是那么需要考慮的問題。·通過在兩次操作中進(jìn)行查詢,網(wǎng)絡(luò)通信量可被任意地減少,這兩次操作是,檢索每個對象的規(guī)范名稱的初始查詢,然后是檢索每個對象的數(shù)據(jù)的第二組GetObjectData調(diào)用。因為GetObjectData調(diào)用可被任意地分塊到一起,所以無需網(wǎng)絡(luò)往返也可從每個對象檢索數(shù)據(jù)。·因為調(diào)用者可指定準(zhǔn)確的查詢過濾器,所以可使數(shù)據(jù)集的大小大大變小。例如,客戶機假脫機程序可在屬于給定用戶的作業(yè)上進(jìn)行枚舉,而不是必須枚舉所有作業(yè)然后過濾掉不屬于給定用戶的作業(yè)?!ひ驗檎{(diào)用者可準(zhǔn)確地指定它們想要檢索哪些字段,所以可以大大減少數(shù)據(jù)量,而優(yōu)于具有不靈活的信息等級系統(tǒng)的當(dāng)前系統(tǒng)。例如,現(xiàn)在要檢索隊列中的作業(yè)數(shù),調(diào)用者必須指定PRINTER_INFO_2,它還包含默認(rèn)的DEVMODE和安全描述符?!こ送ㄖ酝?,該接口當(dāng)前在線路級是無狀態(tài)的。游標(biāo)可能導(dǎo)致更多的服務(wù)器狀態(tài)。維護(hù)游標(biāo)所需的狀態(tài)的額外開銷可能超過從其得到的好處,特別是在給定了緩解的個數(shù)的情況下。然而,在某個時間點在系統(tǒng)中實現(xiàn)游標(biāo)可能會是合乎需要的,特別是在打印系統(tǒng)被調(diào)整為執(zhí)行文檔歸檔,或在可使很大的打印服務(wù)器來處理其中少量隊列處于活動狀態(tài)的非常大量的隊列(在此情形中,避免將對象不必要地拖入存儲器中變得非常重要)的情況下。這一節(jié)描述一種將導(dǎo)致用于查詢的開銷相當(dāng)?shù)偷膬H前向的游標(biāo)的機制。就通知而言,考慮通知不要求對客戶機接口的任何改變。線路接口將把經(jīng)填充的數(shù)據(jù)以分塊形式發(fā)送到客戶機,然后將開始更新客戶機對象。為實現(xiàn)最優(yōu)性能,可將更新與原始填充相互交織。就客戶機游標(biāo)而言,考慮以下情況。所示出并描述的系統(tǒng)的一個目的是盡可能地維護(hù)無狀態(tài)線路協(xié)議。因此,我們定義一組什么對象被游標(biāo)檢索,然后提供達(dá)到這些目的的實現(xiàn)。游標(biāo)合理的語義如下·游標(biāo)僅前向移動。·將被游標(biāo)檢索的一組對象是當(dāng)游標(biāo)被創(chuàng)建時匹配查詢的那些對象減去接下來被刪除的對象。它不包括在游標(biāo)起初被創(chuàng)建以后被創(chuàng)建的任何對象。這是為了防止相對于具有一組迅速改變的對象的服務(wù)器的很慢的客戶機永不終止。所描述的解決方案是為隨每個對象保持一個恒增的順序計數(shù)。當(dāng)游標(biāo)被建立時,當(dāng)前最大的順序計數(shù)號被客戶機記住。一組對象被返回,并且最后一個對象的最大順序計數(shù)被記住。當(dāng)下一組對象被檢索時,它等于此查詢檢索滿足Timestamp(時間戳)>last_max且Timestamp<initial_max的下一個CHUNKSIZE(分塊大小)對象??赡茏詈笫聦嵄砻鳛榉?wù)器上的每個請求執(zhí)行此查詢的額外開銷超過維護(hù)必要的連接以在服務(wù)器上維護(hù)游標(biāo)的上下文的平均額外開銷。一種折衷的解決方案是在由GUID標(biāo)識的服務(wù)器上保持游標(biāo)的高速緩存??蛻魴C將時間戳和GUID提交給服務(wù)器。如果服務(wù)器方的游標(biāo)仍然存在于高速緩存中,則即使用該狀態(tài)。否則,通過執(zhí)行時間戳查詢并將其重新插入到高速緩存中來恢復(fù)游標(biāo)。這允許服務(wù)器以很低的成本丟棄對應(yīng)于很慢的客戶機的狀態(tài)。如果假定主要目的是縮小單個網(wǎng)絡(luò)請求的大小和縮減服務(wù)器上查詢所需的工作集,則CDI接口不一定要求任何改變,遠(yuǎn)程訪問適配器和本地訪問適配器將在客戶機發(fā)布查詢時即透明地使用到服務(wù)器方的游標(biāo)。對于非常龐大的數(shù)據(jù)集,客戶機可能想要自己操縱游標(biāo),以使其不必一次將其所有狀態(tài)都保持在存儲器中。在此情形中,可從CDI接口檢索表示游標(biāo)的接口。不一定要使此調(diào)用被批處理,因為通過蘊含,單個游標(biāo)可檢索大量數(shù)據(jù)。友好名稱解析已經(jīng)在不同地方討論了將友好名稱轉(zhuǎn)換為規(guī)范名稱的概念。友好名稱是對象實例的人類可讀版本,例如,有稱為server.mydomain.org的服務(wù)器的概念就是友好名稱。規(guī)范名稱是標(biāo)識用來與服務(wù)器(即邏輯服務(wù)器寄宿于其上的物理服務(wù)器)通信的協(xié)議的完全無岐義的名稱,并且是對邏輯服務(wù)器對象實例完全無岐義的引用。例如,以上友好名稱可對應(yīng)于以下規(guī)范名稱“{63315ca9-bef6-4cc5-9152-05e369d3d691}\www.realhost.net\{a4b6e956-dee0-46d0-b82c-7ffc8f814e95}\{f091b5a1-ad2a-4dfe-9d37-9592b1ae2512}”。規(guī)范名稱具有完全無岐義這一優(yōu)點,這對計算機而言是極好的。但是它無法由人類容易地輸入。給定規(guī)范名稱,要確定對象的友好名稱(如果這是相關(guān)的)是很容易的。對象只需具有諸如“Object::Name”等可從對象檢索的屬性。但是,如果系統(tǒng)僅具有友好名稱,則它必須能夠確定規(guī)范名稱。在此節(jié)中討論此接口的應(yīng)用程序可調(diào)用方。實現(xiàn)名稱解析器在以下題為“友好名稱解析插件”一節(jié)中討論。以下根據(jù)一個實施例示出客戶機友好名稱解析接口。interfaceIImgCommonData:IUnknown{HRESULTGetFriendlyNameResolver([out]IImgFriendlyNameResolver**ppINameResolver);}interfaceIImgFriendlyNameResolver:IUnknown{HRESULTResolveName([in,string]constwchar_t*pszName,[in,string]constwchar_t*pszClass,[out]IImgCanonicalNameIterator**ppIIterator);HRESULTBeginResolveName([in,string]constwchar_t*pszName,[in,string]constwchar_t*pszClass,[in,unique]IImgCallCompletion*pICallCompletion,[in]void*cookie,[out,unique]IImgAsyncResult**ppIAsyncResult);HRESULTEndResolveName([in]IImgAsyncResult*pAsyncRes,[out]IImgCanonicalNameIterator**ppIterator);HRESULTRemoveName([in,string]constwchar_t*pszName,[in,string]constwchar_t*pszClass);}interfaceIImgCanonicalNameIterator:IUnknown{HRESULTReset(void);voidNext(void);BOOLIsDone(void);IImgCanonicalName*Current(void);}當(dāng)調(diào)用者想要獲得友好名稱解析器時,它們調(diào)用IImgCommonData接口上的GetFriendlyNameResolver方法。友好名稱僅公開兩個邏輯方法(并有對應(yīng)于其中一個的異步調(diào)用模式)。ResolveName給定要解析的名稱(例如“server.mydomain.org”)以及該名稱的類(例如,“Server”),則名稱解析接口調(diào)用友好名稱解析器插件,并將這些插件所返回的所有有效結(jié)果作為IImgCanonicalNameIterator接口返回。該名稱迭代器允許調(diào)用者檢索所有對應(yīng)于該友好名稱的規(guī)范名稱。允許多個規(guī)范名稱返回的原因是,同一個對象可能是經(jīng)由不同路徑可見的。例如,同一服務(wù)器可經(jīng)由SOAP和RPC訪問。ResolveName方法可能要花很長的時間,因為它可能必須查詢多個協(xié)議來查看如何能訪問特定對象。因此,該接口還以BeginResolveName和EndResolveName方法形式提供異步調(diào)用模式。這些方法使用與批處理BeginExecute和EndExecute方法所使用的相同的異步調(diào)用模式。調(diào)用者或可指定回調(diào)接口,或可獲取經(jīng)由IImgAsyncResult返回所返回的系統(tǒng)可等待句柄。當(dāng)解析了所有對應(yīng)的規(guī)范名稱時,它們將受到通知。RemoveName名稱解析器維護(hù)到友好名稱的經(jīng)解析名稱的高速緩存,因為名稱解析可能是非常緩慢并且成本很高的。該高速緩存將隨時間推移被自動刷新。并且如果接下來有任何名稱解析未能解析和高速緩存中相同的名稱,則那些名稱關(guān)聯(lián)將被移除。該行為是,在一定量的時間以后,名稱被視為是失效的。如果調(diào)用者再次請求該名稱,則名稱解析器返回該失效的名稱,但它向名稱解析器插件發(fā)布另一輪名稱解析,如果沒有任何插件返回該名稱,則然后將從高速緩存中移除該名稱。這提供了對名稱非??焖俚慕馕?,但它可能導(dǎo)致在一段時間里失效的名稱綁定被返回。調(diào)用者可解析友好名稱,然后因為在經(jīng)由CDI訪問規(guī)范名稱時失敗來獨立地確定該名稱是失效的。如果它們想要再次請求同一個友好名稱,則它們可能取回同一個失效的名稱。為了避免此情況,可通過RemoveName方法將失效的名稱顯式地從高速緩存中移除。如果調(diào)用者不執(zhí)行此方法,則名稱最終將被清除,這是一種可任選的優(yōu)化。擴展的對象行為前一節(jié)的目的是介紹CDI的接口和基本概念。介紹的目的是主要從用法角度公開該接口。如在前面幾節(jié)中所給出的接口足以允許任何應(yīng)用程序編寫者獲取、設(shè)置、查詢和接收對應(yīng)于該打印系統(tǒng)中的對象的通知。這一節(jié)的焦點是給出額外的行為,該行為可由對象公開以實現(xiàn)新的安全和發(fā)現(xiàn)能力。對象工廠,對象克隆這一節(jié)討論可被用來在系統(tǒng)中創(chuàng)建新的對象、將這些對象(如可適用)傳送到另一個系統(tǒng)中,以及允許新的對象創(chuàng)建用戶界面(UI)被插入的機制。該系統(tǒng)中除了工廠對象以外的所有對象都應(yīng)支持此機制。在圖8中示出此機制,它起到以下討論的基礎(chǔ)的作用。對象創(chuàng)建和克隆機制假定有能夠執(zhí)行以下功能的驅(qū)動程序存儲1.基于UI程序集強名稱向客戶機或服務(wù)器提供UI程序集。2.基于集合程序集強名稱向服務(wù)器方提供集合程序集。強名稱的準(zhǔn)確定義以及它如何與版本化相關(guān)是另一個議題。但是,為上下文目的,考慮以下。強名稱是以一個名字既唯一地標(biāo)識正在使用的程序集的實際實例,又唯一地標(biāo)識該程序集的發(fā)布者的名稱。此機制的一個實現(xiàn)是使用公鑰加密簽署程序集的內(nèi)容,然后取該簽名的加密散列(通常是MD5散列)并將該散列(或該散列的一部分)嵌入到該名稱中。實際上此名稱不僅被綁定到程序集的內(nèi)容,而且它還被綁定到程序集的發(fā)布者。目前沒有已知的技術(shù)可以讓別人創(chuàng)建具有不同功能的另一個程序集并使用我的程序集的強名稱而無需創(chuàng)建非常大量(128位散列需要1038)程序集并在每一個程序集上嘗試整個過程。本質(zhì)的想法是,每個集合提供一公知的對象實例,該對象實例起到一組對象實例的工廠對象的作用。因為不可能預(yù)先知道新對象的構(gòu)造參數(shù),所以該對象用創(chuàng)建新對象實例的稱為Create()的命令實現(xiàn)自定義類型(此例中是Company.Type.1)如果調(diào)用者知道工廠對象和工廠類型,則它們可在新的假脫機程序中創(chuàng)建該類的對象。支持Microsoft.Object.1類型的對象支持克隆。該對象所支持的字段包括集合SN、其創(chuàng)建所使用的工廠對象實例以及三個命令,GetStream、Delete和UpdateFromStream。GetStream將對象的內(nèi)容檢索到流中,Delete刪除對象,而UpdateFromStream基于傳遞給它的流更新對象的狀態(tài)。該對象可支持任何類型的流,但出于互操作性的原因,理想情況是該流為XML。當(dāng)一對象要被克隆時,該對象實例被查詢以獲得其集合SN和工廠對象實例。這些被存儲在流中,接著如流所表示的對象的狀態(tài)也被存儲。為恢復(fù)對象,要從驅(qū)動程序存儲檢索集合并定位工廠對象。然后通過CreateClone命令向工廠對象傳遞流的其余部分。這使工廠創(chuàng)建完全相同的對象實例。注意,流中所有的對象都應(yīng)支持去耦合的UI創(chuàng)建和克隆。但是,為簡略起見,不在其余章節(jié)中示出工廠對象和克隆接口以簡化討論和附圖。分層結(jié)構(gòu)分層結(jié)構(gòu)通常實現(xiàn)兩個目的。第一,它細(xì)分搜索空間以允許對象的高效定位。將CDI分成多個集合、僅在一集合支持給定類的情況下加載該集合的能力、以及將一組動作定向到給定服務(wù)器的能力已經(jīng)實現(xiàn)此目的。第二,它通過允許系統(tǒng)或管理員將對象分組到邏輯分層結(jié)構(gòu)中來提供異類對象的可管理性與發(fā)現(xiàn)。分層結(jié)構(gòu)允許發(fā)現(xiàn),因為每個對象都被定位在邏輯分層結(jié)構(gòu)中的某個地方。因此可構(gòu)建允許用戶進(jìn)而向下鉆入每個對象、直至系統(tǒng)中所有對象已被發(fā)現(xiàn)的瀏覽器。分層結(jié)構(gòu)還可通過允許通過一個管理動作將安全改變應(yīng)用于對象的子樹來提供系統(tǒng)的安全視圖。此機制類似于文件系統(tǒng)實現(xiàn)安全的機制。分層結(jié)構(gòu)對于示出對象之間的關(guān)系而言通常不是很有用。純分層結(jié)構(gòu)只允許一個對象被定位在恰好一個其它對象之下。因此,一個作業(yè)不能同時屬于打印機和服務(wù)器。分層結(jié)構(gòu)還不能高效地示出對象之間的多對一關(guān)系。關(guān)系型模型在指示對象關(guān)系上要強大得多。CDI通過批處理接口上的Query(查詢)動作的QueryBase(查詢基)機制(它返回邏輯上可被視為被另一個對象包含的對象)有效地允許此功能。因為分層結(jié)構(gòu)的第一個目的已由CDI和遠(yuǎn)程訪問適配器路由機制實現(xiàn),并且因為從任何觀點來看CDI的關(guān)系型機制在表示對象關(guān)系上更為強大,所以我們只需要一種支持系統(tǒng)中異類對象的管理和發(fā)現(xiàn)的方法。注意,因為現(xiàn)有的模型足以應(yīng)付大部分情形,所以并非所有對象都必須支持分層結(jié)構(gòu)。由服務(wù)層提供的默認(rèn)的可持久化存儲將自動支持分層結(jié)構(gòu)。因此,本地對象最簡單的實現(xiàn)將自動支持分層結(jié)構(gòu)。會有我們支持可發(fā)現(xiàn)的分層結(jié)構(gòu)、但不支持可修改的分層結(jié)構(gòu)這樣的情形。例如,支持當(dāng)前假脫機程序RPC接口的遠(yuǎn)程適配器可允許客戶機發(fā)現(xiàn)服務(wù)器下的打印機以及打印機下的作業(yè),但不會允許該組織結(jié)構(gòu)被改變。分層結(jié)構(gòu)可通過引入稱為Link(鏈接)類的新類來表達(dá),該類具有一個類型,即帶有一個屬性O(shè)bject(對象)的鏈接類型,Object是可被視為從某個角度來看在當(dāng)前對象“之下”的對象的規(guī)范名稱。當(dāng)想要找出哪些對象實例可從當(dāng)前類以分層結(jié)構(gòu)方式遍歷時,即可用正從其進(jìn)行遍歷的對象實例作為查詢基來查詢Link類。圖9中示出在分層結(jié)構(gòu)中建立的數(shù)個對象的示例。這不包括邏輯系統(tǒng)對象,它們是每個機器上的根對象。鏈接類查詢的實現(xiàn)將由持久對象集合服務(wù)自動提供。但是,任何想要公開可發(fā)現(xiàn)的分層結(jié)構(gòu)的集合可填充鏈接查詢。例如,公開DS對象的集合可枚舉每個DS對象的子對象,然后在當(dāng)父對象被枚舉時將每個對象的特異名稱填充到鏈接表中。安全和分層結(jié)構(gòu)分層結(jié)構(gòu)提供可發(fā)現(xiàn)性和安全。CDI提供一種安全代理,當(dāng)對象的安全描述符被改變時,該安全代理將遍歷子對象以強制執(zhí)行安全繼承規(guī)則。安全將由持久對象集合服務(wù)自動處理,且安全代理將在此集合中的對象上自動運行。將提供稱為邏輯分組的特殊對象,管理員可將任何一組對象放在其下。這允許管理員改變邏輯分組上的ACL,并令它們自動應(yīng)用于該邏輯分組下的所有對象。這允許管理員對其服務(wù)器應(yīng)用其覺得有用的管理分層結(jié)構(gòu),然后將安全規(guī)則應(yīng)用于該分層結(jié)構(gòu)。安全和類混合插入除了用分層結(jié)構(gòu)控制安全以外,該系統(tǒng)還將允許用類來控制安全。這允許諸如提供對在該系統(tǒng)上創(chuàng)建的所有作業(yè)的創(chuàng)建者/所有者管理訪問等特征。在當(dāng)前系統(tǒng)中,類規(guī)則被硬編碼到系統(tǒng)中;將來,任何類都將有混合插入可用。如圖10中所示,類繼承是通過在安全分層結(jié)構(gòu)中公開可編輯的類對象來實現(xiàn)的。這些類對象每一個都將初始包含在創(chuàng)建時應(yīng)用于每個類的默認(rèn)安全描述符。和所有其它對象一樣,它們將從作為整個系統(tǒng)的基對象使用的邏輯系統(tǒng)對象繼承其描述符。當(dāng)適當(dāng)類的對象被創(chuàng)建,父對象和該類對象都被用來推導(dǎo)其安全描述符。圖10也示出邏輯分組對分層結(jié)構(gòu)的作用。這里,管理員創(chuàng)建了兩個邏輯分組,一個能夠控制對任何群集服務(wù)器的訪問,而另一個能夠控制對本地服務(wù)器對象上的打印機的訪問。盡管這里每個情形中僅示出一個對象,但是在每個邏輯分組下可以放置任何數(shù)量的對象。元數(shù)據(jù)在所示出并描述的實施例中,CDI提供將任何對象綁定到遠(yuǎn)程對象的能力,但是調(diào)用者在將對象綁定到遠(yuǎn)程對象以前必須知道該對象支持的字段和命令。大多數(shù)時候,客戶機知道服務(wù)器對象以及它們所支持的接口。如果客戶機不知道,則它將不能正確地工作,因為它需要服務(wù)器對象的先驗知識來進(jìn)行工作。該接口被適應(yīng)于優(yōu)化此行為,而準(zhǔn)確地知道它們將在其中被調(diào)用的上下文的類不需要實現(xiàn)任何元數(shù)據(jù)機制。但是,也有客戶機不具有關(guān)于其正操縱的類的先驗知識的情形。例如,客戶機可能是將CDI調(diào)用轉(zhuǎn)換到托管數(shù)據(jù)提供程序接口的訪問適配器。在此情形中,其客戶機所請求的數(shù)據(jù)不能被先驗地知道,而其正與之通信的服務(wù)器對象也不能被先驗地知道?;蛘?,客戶機可以是允許客戶機或服務(wù)器上所有對象都被瀏覽和操縱而無論對象類型是什么的通用管理UI。為此目的,所示出并描述的實施例提供允許調(diào)用者查詢對象實例以獲得其元數(shù)據(jù)的標(biāo)準(zhǔn)系統(tǒng)類型。這些類型是Type(類型)、Property(屬性)、Command(命令)和Parameter(參數(shù))類型。使用集合適配器服務(wù)實現(xiàn)的類將免費自動獲得完全元數(shù)據(jù)支持。這將從它們將為其每一個類提供的服務(wù)器對象類型映射檢索到。圖11中示出可用對象作為基來查詢以檢索元數(shù)據(jù)的類型。元數(shù)據(jù)是通過首先用對象作為查詢的基來查詢各Type類型來檢索的。Type類型提供邏輯對象實例所支持的所有類型的列表。因為將來系統(tǒng)允許對象被嵌入到其它對象中或擴展其它對象是可能的,所以這些類型將包括對應(yīng)于該對象實例的所有聚集的類型,而不僅僅是底層的基本對象。然后進(jìn)而可查詢每個Type類型所支持的命令或?qū)傩浴H缓?,可查詢每個命令所支持的參數(shù)。查詢基查詢基是不尋常的設(shè)計方面,沒有它系統(tǒng)將是非分層結(jié)構(gòu)的系統(tǒng)。這一節(jié)討論為什么要實現(xiàn)它們,以及它們?nèi)绾斡成涞疥P(guān)系型查詢。查詢基指定源對象,從某種角度來看可認(rèn)為正被查詢的類的示例在源對象“之下”。提供此設(shè)計有以下原因。首先,它允許對要構(gòu)造的子元素進(jìn)行枚舉,否則構(gòu)造者將無從得知如何將關(guān)系表達(dá)為查詢的一個部分。其次,它很好地映射到基于枚舉的下級系統(tǒng)。查詢的基很自然地變成枚舉中的父對象。因此,對于下級對象而言,查詢基和對象狀態(tài)上的過濾器是實現(xiàn)查詢的自然方式。第三,對于具有高度可變組成的對象而言(例如由對象存儲的元數(shù)據(jù)),將查詢作為從父對象出發(fā)的一系列枚舉是更加合乎邏輯的。但是,查詢基需要一些操縱才能映射到關(guān)系型查詢。好在相對而言這很容易實現(xiàn)。為說明起見,上表僅示出打印隊列中的數(shù)個作業(yè)。有兩個字段(在底層數(shù)據(jù)庫中實現(xiàn)為外來關(guān)鍵字)存儲作業(yè)與之相關(guān)聯(lián)的對象的規(guī)范名稱。引用遠(yuǎn)程對象的每個列都知道遠(yuǎn)程對象類。當(dāng)有對特定基對象的查詢時,該對象的類被相關(guān)到該對象中的一邏輯字段,然后該查詢被擴展以包括這一具有正確值的字段。例如,如果有對于Base(基)=“{SSSS}”、BaseClass(基類)==“Server”(服務(wù)器)、并帶查詢串“Jobs:Size<150KB”的查詢,則這將被轉(zhuǎn)換為以下查詢Jobs:Server=”{SSSS}”AND(Jobs:Size<150KB).這將返回正確的結(jié)果,即Fred的作業(yè)。此轉(zhuǎn)換將在集合適配器服務(wù)中被自動執(zhí)行。在服務(wù)器對象類型映射中它將需要稍多一些元數(shù)據(jù),因為我們需要知道哪些字段可起到查詢基的作用,以及它們對應(yīng)于哪些類。CDI實現(xiàn)前一節(jié)描述了希望從對象獲得的行為,并描述了向客戶公開的接口。這一節(jié)描述服務(wù)器方的CDI實現(xiàn)。它描述CDI所提供的服務(wù)以及插件模型。圖12示出CDI的主要組件,以及被插入到該系統(tǒng)中的各種插件。首先,將提供對其中每個主要組件的描述,然后將提供對CDI盒本身中的組件的描述。集合適配器服務(wù)由系統(tǒng)提供,但是它被視為是由插件承載的單獨的服務(wù),而不是CDI本身的一個部分。集合適配器服務(wù)在下一節(jié)討論。應(yīng)用程序到應(yīng)用程序的接口是前幾節(jié)的主要焦點。應(yīng)用程序從CDI請求批處理接口,記錄數(shù)個動作然后執(zhí)行它們。當(dāng)執(zhí)行完成時,應(yīng)用程序可獲得結(jié)果。路由器執(zhí)行這些動作導(dǎo)致批次被路由器路由并被傳遞給插件。路由器在一次調(diào)用中找出批次中被定址到同一插件的連續(xù)范圍,并將那些范圍傳遞給插件。因此,插件本身仍可保持批處理行為。取決于應(yīng)用程序所調(diào)用的語義,這些部分可被并行地、串行地傳遞給插件,或可將事務(wù)對象與批次相關(guān)聯(lián)以允許插件協(xié)調(diào)事務(wù)。插件插件是由DLL結(jié)合DLL清單和配置信息公開的接口。單個DLL可公開一個或多個插件接口。在所示出并描述的實施例中,插件接口包括帶有一個方法的一個工廠接口,和僅帶有兩個方法——AsyncProcessRequest和Shutdown的插件接口(IImgBatchCollection)。插件接口仍按批次形式接受其操作。因此它是用于遠(yuǎn)程化到其它也支持批次的系統(tǒng)的邏輯接口。為此目的,在所示出并描述的實施例中,提供了以下插件本地訪問適配器、遠(yuǎn)程訪問適配器、沙箱適配器、以及自適應(yīng)插件,其中每一個都在以下單獨討論。本地訪問適配器提供對本地服務(wù)或每用戶服務(wù)的訪問。目前此插件使用異步COM,但沒有任何特殊理由不能使用任何其它遠(yuǎn)程化機制。遠(yuǎn)程訪問適配器提供對遠(yuǎn)程機器的訪問,并將很大程度上使用和本地訪問適配器相同的機制,僅有一些差異用于減少服務(wù)器上的每客戶機狀態(tài)。沙箱適配器被用來在將請求分組到批次中的范圍內(nèi)保持應(yīng)用程序的工作。這也意味著同一個通用插件模型可被進(jìn)程內(nèi)或進(jìn)程外組件使用,如果希望的話,我們甚至能用沙箱法構(gòu)造系統(tǒng)組件。系統(tǒng)中處CDI以外的所有部分將作為插件公開。自適應(yīng)插件的形式極其簡單,但它要求插件在一次異步調(diào)用中解釋排隊的批處理操作,這可能會很復(fù)雜。為此原因,提供了集合適配器服務(wù)(CAS)。集合適配器服務(wù)允許對象(IImgObject)的多個對象集合(IImgObjectCollection)被插入到其中,而它進(jìn)而解釋被批處理的調(diào)用,并將這些調(diào)用轉(zhuǎn)換為對所提供的集合和對象的調(diào)用。集合適配器服務(wù)提供對這些接口的同步和異步實現(xiàn)的高效處理。集合接口足夠?qū)挿憾杀挥脕碓L問下級協(xié)議。在這些情形中沒有性能損失,因為它們通常不支持批處理。服務(wù)在所示出并描述的實施例中,CDI提供一組服務(wù)。其中大多數(shù)可從插件訪問。這些服務(wù)是公開的,并平等地向CAS和任何其它插件公開。這允許覺得CAS過于有限的獨立軟件供應(yīng)商或獨立硬件供應(yīng)商自己來實現(xiàn)相同的功能。明確的目的是允許CAS解決大多數(shù)情形,所有系統(tǒng)提供的對象將會使用它。CDI所提供的服務(wù)包括查詢編譯器、工作流程、事務(wù)、改變范圍、Variant和類型映射,其中每一個都在以下單獨討論。查詢編譯器能夠?qū)?yīng)用程序提供的查詢編譯為語法分析樹和過濾器這兩種形式中的一種。語法分析樹在插件想要將查詢轉(zhuǎn)換為另一種形式的查詢的情況下是很有用的,這比試圖自己來重新進(jìn)行語法分析要簡單,因為括號和運算符優(yōu)先級已被語法分析器解析,而一些基本的構(gòu)造良好性檢查已被語法分析器執(zhí)行。過濾器可被綁定到對象,并提供允許調(diào)用者檢查給定對象的狀態(tài)是否匹配被傳入的查詢的方法——“DoesMatch”。工作流程是每當(dāng)應(yīng)用程序執(zhí)行進(jìn)入CDI的調(diào)用時被實例化的接口。它對應(yīng)于用戶動作的邏輯執(zhí)行。工作流程可調(diào)度工作,并將在工作流程被取消時(通常是因為來自用戶的原始調(diào)用被取消)通知與其相關(guān)聯(lián)的工作項目。工作流程可跟蹤一組令牌以檢測并防止遞歸。當(dāng)插件因為來自CDI的調(diào)用的原因而想要進(jìn)行進(jìn)入系統(tǒng)的調(diào)用時,它必須使用和發(fā)起的調(diào)用中相同的工作流程。通過特殊的僅服務(wù)器方調(diào)用(IImgCommonDataServer::RecurseDataBatch)來實現(xiàn)此目的。當(dāng)執(zhí)行遞歸時,必須將一令牌插入到流程中,稍后可使用該令牌來檢查同一操作是否在同一流程上重復(fù)發(fā)生,并因此退出遞歸。工作流程還將跟蹤原始調(diào)用者的令牌。當(dāng)插件異步并獨立地進(jìn)入CDI進(jìn)行調(diào)用時,它或可通過客戶機接口來實現(xiàn)此功能,或可創(chuàng)建它自己的工作流程并調(diào)用RecurseDataBatch。如果調(diào)用者請求事務(wù),則此對象被創(chuàng)建并與批次相關(guān)聯(lián)。事務(wù)提供一種將一個事務(wù)式集合和一組從屬項目與事務(wù)相關(guān)聯(lián)的機制。它既提供到事務(wù)的同步接口,也提供到事務(wù)的異步接口。當(dāng)批次完成執(zhí)行時,事務(wù)被提交。結(jié)果被發(fā)送到存儲,如果存儲正確地更新,則從屬項目被運行。為了符合從屬項目的資格,項目必須不能使提交請求失敗。這被用來使從屬于一狀態(tài)改變的活的在存儲器中的對象被傳播到存儲中。如果插件想要將事務(wù)擴展成包括其它對象(例如,為了實現(xiàn)依次刪除其它對象的“Delete”命令),則它可在經(jīng)由RecurseDataBatch進(jìn)入CDI進(jìn)行回調(diào)時指定同一事務(wù)。每個遞歸上的所有改變都將被保持為未決狀態(tài),直至最外圍的批次成功地完成。改變范圍涉及服務(wù)器方表示每個通道的改變處理器。可在事務(wù)上插入改變范圍。Variant已在前面章節(jié)討論。Variant可由客戶機方或服務(wù)器方使用。類型映射也已在前面章節(jié)討論。優(yōu)化的映射僅對服務(wù)器方可見。插件接口在所示出并描述的實施例中,插件接口是使用類似COM的對象實例化模型來實例化的。它不要求插件在注冊表中注冊它的類ID。圖13中示出實例化插件的過程。在所示出并描述的實施例中,所有插件都作為CDI配置的一個部分被存儲在WMI.Config中。其中一些插件數(shù)據(jù)將由WMI.Config從插件DLL的XML配置文件合成(這對基于XCOPY的解決方案很有用)。CDI配置包含插件DLL的列表。對于每個DLL,我們列出每一個所支持的集合GUID,以及在每個邏輯集合中所支持的類。每個DLL還有一些相關(guān)聯(lián)的初始化數(shù)據(jù)。這通常表示DLL所支持的對象將被持久化到并從該處檢索的位置。當(dāng)路由器想要將插件接口實例化時,它檢索集合GUID,找出對應(yīng)的DLL,然后調(diào)用DllGetClassObject:HRESULTDllGetClassObject(INREFCLSIDrclsid,INREFIIDriid,OUTVOID**ppv);然后我們請求CLSID_IImgBatchCollection和IID_IImgBatchCollectionFactory。DLL隨即返回一個類工廠,它能夠返回該插件所支持的IImgBatchCollection的各種實例。IImgBatchCollectionFactory支持以下接口interfaceIImgBatchCollectionFactory:IUnknown{HRESULTLockServer([in]BOOLfLock);////待辦pInit應(yīng)被基于WMI.Config的更加切合實際的初始化系統(tǒng)取代。//HRESULTCreateInstance([in]IImgCommonDataServer*pICommonDataServer,[in]REFGUIDcollectionGuid,[in,string]constwchar_t*pInit,[in]REFIIDriid,[out]void**ppvObj);}在CreateInstance(創(chuàng)建實例)期間,向工廠傳遞以下信息·IImgCommonDataServer接口。此接口繼承自IImgCommonData,并且還包括一些插件專屬的訪問服務(wù)器方的服務(wù)的方法。注意插件不應(yīng)調(diào)用CoCreateInstance(CLSID_IImgCommonData),因為這將創(chuàng)建客戶機接口。當(dāng)最后一個客戶機接口被釋放時,系統(tǒng)關(guān)閉,如果服務(wù)器方插件保留了客戶機接口,則系統(tǒng)不關(guān)閉?!ぜ螱UID。這和CDI配置中給出的是相同的GUID。工廠可根據(jù)此GUID選擇實例化不同的IImgBatchCollection接口?!こ跏蓟瘮?shù)據(jù)-此數(shù)據(jù)將從WMI.Config檢索。目前這由串表示。插件使用此初始化數(shù)據(jù)來選擇從何處獲得其對象?!iid-這是CDI所請求的接口。目前僅IID_IImgBatchCollection被請求,但此處還可請求其它將來的接口。插件所返回的接口如下interfaceIImgBatchCollection:IUnknown{HRESULTAsyncProcessRequest([in]IImgServerItemCompletion*pIItemCompletion,[in]ULONGStartIndex,[in]ULONGEndIndex,[in]IImgBatchArray*pIBatchArray);HRESULTShutdown([in]EImgShutdownReasoneReason);};如果有任何來自批次數(shù)據(jù)的目的地是插件,則AsyncProcessRequest接口被調(diào)用。向該集合傳遞以下數(shù)據(jù)·IImgServerItemCompletion接口。此接口支持單個方法-“Done”,它在請求被完全處理以后被調(diào)用。調(diào)用者可立即從AsyncProcessRequest返回。調(diào)用者必須調(diào)用“Done”除非它們未能通過AsyncProcessRequest調(diào)用。未能調(diào)用“Done”導(dǎo)致客戶機的Execute調(diào)用沒有完成?!atchArray(批數(shù)組),此接口提供對客戶機所請求的動作的訪問?!づ鷶?shù)組的開始和結(jié)束索引。這允許路由器創(chuàng)建一個批次,然后該批次被各個插件共享。如果客戶機請求并行執(zhí)行語義,則各插件可被并行執(zhí)行。批數(shù)組具有以下接口typedefstruct{EImgBatchOptionseItemType;EImgActionCompletionStatuseCompletionStatus;HRESULThrCallResult;IImgErrorInfo*pErrorInfo;union{[case(BatchGetObjectData)]ImgBatchGetObjectDataObjectGetData;ImgBatchSetObjectDataObjectSetData;ImgBatchObjectCommandObjectCommand;ImgBatchObjectQueryObjectQuery;ImgBatchNotifyRegistrationNotifyRegistration;};}ImgBatchItem;interfaceIImgBatchArray:IUnknown{HRESULTItemAt([in]ULONGIndex,[out]ImgBatchItem**ppBatchItem);////這些訪問器提供到批數(shù)組中其它數(shù)據(jù)的訪問。//EImgBatchSemanticsGetBatchSemantics(void);IImgBatchTransaction*GetAliasedBatchTransaction(void);IImgWorkFlow*GetAliasedWorkFlow(void);};可從批數(shù)組檢索批語義、任何相關(guān)聯(lián)的事務(wù)和工作流程。并不返回帶有遞增引用計數(shù)的接口,因為它們對于批數(shù)組使用別名。ItemAt方法返回給定索引處的批動作。這包含給出項目類型的枚舉。它還包含插件可設(shè)置以指示項目是否完成以及任何出錯信息的字段。它包含一聯(lián)合,該聯(lián)合包含由調(diào)用者傳入的對應(yīng)動作的參數(shù)。截取既然已經(jīng)定義了插件接口和路由器,以下對截取的實現(xiàn)進(jìn)行討論。在所示出并描述的實施例中,截取被實現(xiàn)為批處理路由器可向其發(fā)送數(shù)據(jù)的另一個插件接口。但是,和為普通插件存儲的配置信息不同,普通插件僅要求集合ID(或用于查詢的類)來進(jìn)行路由,而截取插件指定以下信息段·截取動作。截取器可指定它想要俘獲獲取、設(shè)置、查詢、命令還是通知?!そ厝☆悺=厝∑髦付ㄋ胍驗槟念悓ο蠖徽{(diào)用。該類可被指定為‘*’,在此情形中將為所有的類注冊截取器?!そ厝〖稀=厝∑髦付ㄋ胍厝∑鋵ο蟮募系奈ㄒ籊UID。此集合可被指定為‘*’,在此情形中將為所有集合注冊截取器?!そ厝ο?。截取器可指定它想要監(jiān)視(如果它這樣做,則它應(yīng)當(dāng)截取該對象的Delete命令以移除截取)的對象的唯一對象ID。如果指定了‘*’,則為所有的類調(diào)用截取器。截取表中的每個注冊都被分配一個GUID。該截取機制將使用“命令鏈”模式。批處理路由器所采取的動作如下1.在將批次中的給定項目路由到集合以前,路由器首先使用上述字段檢查是否為該調(diào)用注冊了截取器。2.如果有,按照相同規(guī)則找到目標(biāo)為同一截取器的一組連續(xù)的動作。3.與截取注冊相關(guān)聯(lián)的GUID被插入到工作流程中,并且截取器被調(diào)用。在這個時間點上,如向任何其它插件一樣向截取器傳遞批處理動作。它按以下兩種方式中的一種改變動作的執(zhí)行1.它對路由器調(diào)用RecurseBatchActions(),并再次傳入工作流程加上原始的批處理動作。這不導(dǎo)致其中任何動作被修改,但它允許截取器讀取這些動作并自己執(zhí)行其它動作(例如,如果它是同步器,則它將在被高速緩存的數(shù)據(jù)失效的情況下用這來觸發(fā)同步動作。)2.它解釋每個批處理動作,然后通過調(diào)用RecurseDataBatch來修改它們,并再次傳入工作流程。此選項允許截取器改變動作的結(jié)果,但它(有意地)更加難以實現(xiàn)。例如,為改變“Get”(獲取)的結(jié)果,必須實例化一臨時代理對象來保持實際對象獲取的結(jié)果,還必須注冊新的類型映射才能寫此臨時對象。這些調(diào)用中任何一個都將導(dǎo)致進(jìn)入批處理路由器的回調(diào)。除了不進(jìn)入任何將其GUID令牌列在工作流程中的截取器進(jìn)行調(diào)用以外,批處理路由器執(zhí)行和以前完全相同的查找。因此,進(jìn)而每個截取將被窮舉,直至動作被路由到目標(biāo)對象。同樣的機制防止一組行為良好的截取器和對象出現(xiàn)遞歸,因為路由器在調(diào)用出現(xiàn)遞歸的情況下將自動忽略已被調(diào)用的截取器。因為截取器負(fù)責(zé)鏈接調(diào)用,所以它可選擇在鏈接以前或以后執(zhí)行動作。它可改變批次的語義。通常,如果批次不是事務(wù)式的,則它可能想要確保截取是事務(wù)式的。因為它是被異步調(diào)用的,所以它甚至可與被截取的動作并行地執(zhí)行其截取。截取的用途截取對兩個目的而言是有用的——系統(tǒng)擴展或方面擴展。截取可被IHV用來擴展批處理動作的行為。例如,當(dāng)隊列被暫停時,可能需要由驅(qū)動程序采取另一個動作。只要這些擴展不試圖改變原始動作的結(jié)果,它們就是相當(dāng)安全的。為此原因,使RecurseBatchActions方法更容易實現(xiàn)。改變批處理動作的結(jié)果將會困難得多,因為它要求截取和修改所有參數(shù),包括如類型映射、客戶機對象和客戶機對象集合等一些難以處理的參數(shù)。還可設(shè)想將截取作為一種用于維護(hù)兼容性以及用于修補系統(tǒng)的機制。例如,如果對系統(tǒng)的修訂導(dǎo)致一插件行為異常,則可創(chuàng)建截取器以將進(jìn)入其中的調(diào)用改變成其所理解的調(diào)用。因此,可通過提供截取器(例如,通過在帶有過長的串的調(diào)用到達(dá)目標(biāo)對象以前截取該調(diào)用來修補安全漏洞的截取器)來服務(wù)系統(tǒng)。這甚至可被相當(dāng)一般地實現(xiàn),例如,可編寫拒絕所有大于MAX_PATH的串的截取器,或可提供每個字段的適當(dāng)串長度的表。截取最有用的是在實現(xiàn)跨越/修剪大量對象的系統(tǒng)的一個方面。例如,可編寫將所有符合特定模式(例如,它們因“訪問被拒絕”原因而失敗)的動作記錄在系統(tǒng)中的截取器。對象命令對象命令和對象屬性不同,原因在于對象命令僅在服務(wù)器方被調(diào)用。這是因為命令調(diào)用是通過將來自客戶機的Variant數(shù)組傳遞給服務(wù)器并返回來執(zhí)行的。沒有被調(diào)用的客戶機方代理對象的概念。數(shù)據(jù)表示如下所示。typedefstruct{ULONGcParams;ImgVariant*aParams;}ImgReturnParams;interfaceIImgCommand:IUnknown{HRESULTBeginCommand([in]void*pObject,[in]ULONGcInputParams,[in,size_is(cInputParams)]ImgVariant*aInputParams,[in]IImgWorkFlow*pIWorkFlow,[in]IImgCommonDataServer*pICDIS,[in]IImgServerItemCompletion*pIComplete,[out]void**ppContext);HRESULTEndCommand([in,unique]void*pContext,[out]ImgReturnParams*pReturnParams);};////定義一結(jié)構(gòu)來描述一參數(shù)。//typedefstruct{ImgTypetype;constwchar_t*description;}ImgParameterDescriptions;////定義一結(jié)構(gòu)來描述數(shù)個參數(shù)。//typedefstruct{ULONGcParams;ImgParameterDescriptions*aParams;}ImgParametersDescription;////定義一結(jié)構(gòu)來保存命令。//typedefstruct{[string]constwchar_t*type;constwchar_t*command;IImgCommand*pICommand;constwchar_t*description;ImgParametersDescriptioninputParameters;ImgParametersDescriptionoutputParameters;}ImgCommand;////定義若干命令。//typedefstruct{ULONGcCommands;ImgCommand*aImgCommand;}ImgCommandsDescription;////服務(wù)器類描述可包含命令,這與客戶機類描述不同。//typedefstruct{ImgClassDescriptionvalues;ImgCommandsDescriptioncommands;}ImgServerClassDescription;如從以上代碼可以看到,服務(wù)器類描述和客戶機類描述是相同的,但它還包括對一組命令的描述。命令具有類型、命令和描述。它包含指向命令接口的指針。命令接口和訪問屬性中所使用的訪問器接口以類似方式工作。向命令接口傳遞它必須對其應(yīng)用該命令的對象、以及包含對應(yīng)于該命令的輸入?yún)?shù)的ImgVariant數(shù)組。每個命令都可被異步執(zhí)行,這就是接口既有BeginCommand又有EndCommand方法的原因。每個命令還定義其所有參數(shù)的類型,并且還具有對應(yīng)于每個命令的所有描述的列表。和屬性訪問器一樣,可在動態(tài)類型之上構(gòu)建命令。但是,因為在基礎(chǔ)級它們對應(yīng)于執(zhí)行動作(和檢索數(shù)據(jù)相對),并且因為在調(diào)用命令時,并非必須為線路封送目的構(gòu)造動態(tài)代理對象,所以這可能不像對屬性那么有用。它在經(jīng)由截取擴展命令的情況下可能有用。IATL命令I(lǐng)ATL提供一種將CDI命令直接映射到C++類方法調(diào)用的機制,正如它提供一種將CDI類型映射屬性直接映射到C++字段和方法的機制。IATL允許調(diào)用者將命令實現(xiàn)為在其中為實現(xiàn)者自動構(gòu)建異步BeginCommand、EndCommand對的單個方法。這在實現(xiàn)者想要實現(xiàn)不進(jìn)行任何IO的命令的情況下是很有用的。或者,IATL使類提供兩個方法,并異步地實現(xiàn)該命令。用來構(gòu)建IATL的機制在以下代碼節(jié)選中概述。namespaceImg{namespaceiatl{structCommandParams{IImgWorkFlow*pIWorkFlow;IImgCommonData*pICDI;};structInCommandParams{IImgServerItemCompletion*pIItemCompletion;IImgWorkFlow*pIWorkFlow;IImgCommonDataServer*pICDIS;void**ppContext;};structOutCommandParams{void*pContext;};}//namespaceiatl}//namespaceImgclassServerPrinterCommandBase{public:ServerPrinterCommandBase(void);ServerPrinterCommandBase(constServerPrinterCommandBase&source);HRESULTPrint(INImg::iatl::CommandParams*pParams,INBSTRpszPrintJob);};classServerPrinter:publicImg::iatl::TIMCServerObject<ServerPrinter>,publicServerPrinterCommandBase{public:HRESULTRandom(INImg::iatl::CommandParams*pParams,OUTULONG*pRand);HRESULTPrintAndRandom(INImg::iatl::CommandParams*pParams,INBSTRpszPrint,OUTDOUBLE*pRand);HRESULTBeginNothing(INImg::iatl::InCommandParams*pParams,INBSTRpszPrint);HRESULTEndNothing(INImg::iatl::OutCommandParams*pParams,OUTBSTR*pbstrPrint);HRESULTStartNotifications(INImg::iatl::CommandParams*pParams);HRESULTBeginDelete(INImg::iatl::InCommandParams*pParams);HRESULTEndDelete(INImg::iatl::OutCommandParams*pParams);};////用于構(gòu)建ServerPrinterCommandBase的命令調(diào)用的IATL表//IMG_ATTR_TABLE_BEGIN(ServerPrinterCommandBase,Img::iatl::CommandMap)Type(L"PrinterBase"),Command(glIn,IMG_ATTR_METHOD(ServerPrinter::Print),L"Print",L"Thisprintsoutsomething"),InDescrip(L"Thenameofthefiletoprint"),IMG_ATTR_TABLE_END////用于構(gòu)建ServerPrinter的命令調(diào)用的IATL表//IMG_ATTR_TABLE_BEGIN(ServerPrinter,Img::iatl::CommandMap)Type(L"PrinterBasic"),Command(glOut,IMG_ATTR_METHOD(ServerPrinter::Random)),OutDescrip(L"Arandomnumberisreturned"),Command(glInlOut,IMG_ATTR_METHOD(ServerPrinter::PrintAndRandom)),InDescrip(L"Somethingthatwillbeoutputtothedebugger"),OutDescrip(L"Afractionalrandomnumber"),Inherits(IMG_ATTR_INHERIT_TABLE(ServerPrinterCommandBase)),Command(IMG_ATTR_METHOD(ServerPrinter::BeginNothing),IMG_ATTR_METHOD(ServerPrinter::EndNothing),L"Nothing"),InDescrip(L"Somethingthatwillbeoutputtothedebugger"),OutDescrip(L"Somethingelsethatwillbereturned"),Command(IMG_ATTR_METHOD(ServerPrinter::BeginDelete),IMG_ATTR_METHOD(ServerPrinter::EndDelete),L"Delete",L"Deletetheobject"),Command(IMG_ATTR_METHOD(ServerPrinter::StartNotifications)),Command(glIn,IMG_ATTR_METHOD(ServerPrinter::Clone)),InDescrip(L"Thenewnameoftheprinterthatiscloned"),IMG_ATTR_TABLE_END此節(jié)選示出可將來自類的方法作為CDI命令公開的數(shù)種不同的方式。Print(打印)命令在ServerPrinterCommandBase中實現(xiàn),并且被實現(xiàn)為單個同步方法。所有同步方法接收Img::iatl::CommandParams參數(shù)作為其第一個變量。此結(jié)構(gòu)持有與命令相關(guān)聯(lián)的工作流程和公共數(shù)據(jù)接口。第二個參數(shù)映射到第一個命令變量,依此類推。為了消除哪些參數(shù)是輸入?yún)?shù)以及哪些是輸出參數(shù)的岐義,調(diào)用者必須向Command(命令)函數(shù)提供一指示該方法具有多少輸入和輸出函數(shù)的參數(shù)。例如,當(dāng)引用打印命令時Command(glIn,IMG_ATTR_METHOD(ServerPrinter::Print),L"Print",L"Thisprintsoutsomething"),glIn參數(shù)指示這是具有一個輸入?yún)?shù)的命令。任何可作為命令被調(diào)用的方法中,輸入?yún)?shù)都必須在輸出參數(shù)以前。正如屬性類型映射,命令類型映射可從基類型繼承到派生類型中。這是用Inherits(繼承)函數(shù)來實現(xiàn)的。Inherits(IMG_ATTR_INHERIT_TABLE(ServerPrinterCommandBase)),命令參數(shù)的類型將被從方法變量自動推導(dǎo)。但是,在表中可任選的描述字段必須被提供。這是經(jīng)由InDescrip和OutDescrip函數(shù)實現(xiàn)的。例如Command(glInlOut,IMG_ATTR_METHOD(ServerPrinter::PrintAndRandom)),InDescrip(L"Somethingthatwillbeoutputtothedebugger"),OutDescrip(L"Afractionalrandomnumber"),這里Command函數(shù)提供命令的基本定義,而InDescrip和OutDescrip函數(shù)分別描述第一輸入和參數(shù)。如果描述了一個以上參數(shù),則可對InDescrip和OutDescrip進(jìn)行多次調(diào)用。IATL命令映射所示出的其它值得注意的特征是實現(xiàn)異步命令的能力。這由ServerPrinter類上的BeginNothing和EndNothing方法示出HRESULTBeginNothing(INImg::iatl::InCommandParams*pParams,INBSTRpszPrint);HRESULTEndNothing(INImg::iatl::OutCommandParams*pParams,OUTBSTR*pbstrPrint);在命令描述中,這被以下代碼引用Command(IMG_ATTR_METHOD(ServerPrinter::BeginNothing),IMG_ATTR_METHOD(ServerPrinter::EndNothing),L"Nothing"),InDescrip(L"Somethingthatwillbeoutputtothedebugger"),OutDescrip(L"Somethingelsethatwillbereturned"),此例中的Command函數(shù)無需被告知哪些是輸入?yún)?shù),哪些是輸出參數(shù),因為輸入?yún)?shù)根據(jù)定義是由Begin方法提取,而輸出參數(shù)根據(jù)定義是由End方法返回。在此情形中,Begin方法和End方法對于同步(單個方法)命令采取不同的結(jié)構(gòu),即Img::iatl::InCommandParams和Img::iatl::OutCommandParams。InCommandParams包含指示操作完成的回調(diào)接口,以及可被保存并與該操作相關(guān)聯(lián)的上下文信息。向End方法傳回該上下文信息,且該方法可返回該命令的結(jié)果作為出錯代碼,或返回一組返回參數(shù)。查詢編譯器查詢編譯器提供一種將CDI查詢編譯為可對任何具有類描述的對象應(yīng)用的過濾器或語法分析樹。由查詢編譯器公開的接口在以下代碼節(jié)選中示出。typedefstruct{EImgParseTypeseConstType;union{[case(ParseTypeInteger)]LONGLONGintval;DOUBLEdblval;[string]constwchar_t*String;};}ImgParseConstant;typedefstruct{EImgParseIdentTypeseType;constwchar_t*ptype;constwchar_t*pfield;void*pCookie;}ImgParseIdentifier;typedefstruct{ImgParseIdentifier*pIdentifier;EImgComparisonOperatorcompOperator;ImgParseConstantconstant;}ImgParseComparison;struct_tagImgQueryNode;typedefstruct{EImgBooleanOperatorboolOperator;struct_tagImgQueryNode*pLeft;struct_tagImgQueryNode*pRight;}ImgBooleanNode;typedefstruct_tagImgQueryNode{EImgNodeTypeeNodeType;union{[case(ComparisonQueryNode)]ImgParseComparisoncomparison;ImgBooleanNodeNode;};}ImgQueryNode;typedefstruct_tagImgQueryNode{EImgNodeTypeeNodeType;union{[case(ComparisonQueryNode)]ImgParseComparisoncomparison;ImgBooleanNodeNode;};}ImgQueryNode;interfaceIImgQueryTree:IUnknown{ImgQueryNode*Root(void);}interfaceIImgQueryFilter:IUnknown{HRESULTDoesMatch([in]void*ServerClass,[out]BOOL*pbMatch);HRESULTClassMapping([out]IImgOptimizedMap**ppIOptMap);}interfaceIImgQueryFilterFactory:IUnknown{HRESULTGetFilter([in]constImgClassDescription*ServerClass,[in]REFGUIDClassId,[out]IImgQueryFilter**ppIExec);}interfaceIImgCommonDataServer:IImgCommonData{////這些方法被用來編譯對服務(wù)器對象的查詢。//HRESULTCompileQuery([in,string]constwchar_t*pQuery,[out]IImgQueryFilterFactory**ppIQueryFilterFactory);HRESULTCompileQueryTree([in,string]constwchar_t*pQuery,[out]IImgQueryTree**ppIQueryTree);}服務(wù)器方CDI實例提供編譯查詢的機制。如果需要查詢過濾器,則使用IImgCommonData服務(wù)器接口的CompileQuery方法。如果需要語法分析樹,則調(diào)用CompileQueryTree方法。查詢過濾器作為工廠被返回。當(dāng)特定的類描述被傳遞給查詢過濾器工廠時,則查詢過濾器被返回。覆蓋之下的查詢過濾器對照由該查詢動態(tài)生成的類構(gòu)建類型映射。當(dāng)它被綁定到服務(wù)器對象時,它對照服務(wù)器對象構(gòu)建優(yōu)化映射。此優(yōu)化映射被用來填充隨即將對照其應(yīng)用該查詢的查詢對象。從查詢過濾器工廠被返回的查詢過濾器由定義綁定到特定服務(wù)器類??蓪Χ鄠€服務(wù)器類對象實例應(yīng)用該查詢過濾器。它不是線程安全的。如果調(diào)用者想要從一不同的線程使用同一個查詢,則它們可從同一個查詢過濾器工廠獲得不同的查詢過濾器實例,并在不同的線程中使用該實例。查詢過濾器具有可對支持類描述的任何類應(yīng)用的優(yōu)點。但是,對于要對類應(yīng)用的過濾器而言,該類必須被實例化,并且可能被該過濾器匹配的所有實例必須被評估。這對相對較小的一組對象(對于現(xiàn)代計算機而言可能在10,000數(shù)量級)而言這是可以的,但是它對于一大組對象執(zhí)行效果就極其糟糕。對于一大組對象,應(yīng)當(dāng)使用諸如由SQL所使用的查詢機制。但是,CDI查詢句法不等同于SQL句法。為解決這一問題,可改為編譯查詢樹,然后將該樹轉(zhuǎn)換為SQL查詢。允許CDI查詢編譯器運行就允許諸如運算符優(yōu)先級和括號等問題由CDI編譯器與它將如何處理對查詢過濾器的相同查詢等問題一致地評估。從CompileQueryTree方法返回的接口通過Root(根)方法返回已編譯查詢樹的別名。被所返回的語法分析樹占據(jù)的內(nèi)存在IImgQueryTree接口被釋放時將被返回給系統(tǒng)。在一個實施例中,語法分析樹以查詢節(jié)點為開始;該查詢節(jié)點或可是比較,或可是布爾節(jié)點。如果它是布爾節(jié)點,則該節(jié)點具有一個運算符,并進(jìn)而包含兩個查詢節(jié)點。這是允許構(gòu)建語法分析樹的構(gòu)造。如果是比較節(jié)點,則該比較包含語法分析標(biāo)識符和常量。如果該標(biāo)識符在同一表達(dá)式中出現(xiàn)兩次,如以下查詢中可見“Printer.cJobs>10ANDPrinter.cJobs<100”,則相同的ImgParseIdentifier實例將在語法分析樹中出現(xiàn)兩次。pCookie字段是樹中的占位符,它允許調(diào)用者將它們的標(biāo)識符的概念存儲在cookie中。例如,如果Printer.cJobs轉(zhuǎn)換為數(shù)據(jù)庫中的NumberOfJobs列,則這可被存儲在cookie中。除了提供可擴展性點以外,cookie被忽略。事務(wù)事務(wù)是CDI用來確保操作或是完全成功,或如果失敗則不會在機器上存儲任何中間狀態(tài)的機制。處理事務(wù)的實際機制被分布在CDI和CAS之間。CDI提供處理事務(wù)和工作流程的接口。CAS提供確保事務(wù)正確和提供死鎖釋放鎖定策略所需的機制。每個事務(wù)都由恰好一個事務(wù)對象控制。每個事務(wù)對象都具有一個邏輯存儲對象。系統(tǒng)中的每個邏輯存儲由GUID應(yīng)用。存儲對象協(xié)調(diào)處理事務(wù)需要協(xié)調(diào)的任何持久化狀態(tài)。在存儲不是分布式資源管理器(DRM)的情況下,如果考慮系統(tǒng)不能保證對兩個事務(wù)式存儲的兩次提交保證成功,則僅一個存儲的限制是合理的。在存儲是DRM的情形中,則事務(wù)將協(xié)調(diào)地在一個邏輯存儲之上,即由分布式事務(wù)協(xié)調(diào)器(DTC)所提供的邏輯存儲,如COM+中可找到的。每個事務(wù)還持有若干從屬動作。規(guī)則是從屬動作必須既能夠提交又能夠反轉(zhuǎn)其操作。從屬動作一般被用來將被高速緩存的狀態(tài)(或鎖)耦合到持久存儲。例如,CAS在將事務(wù)應(yīng)用于存儲以前克隆每個對象,如果存儲成功地提交了改變,則被克隆的對象被交換到高速緩存中。事務(wù)接口如下所示typedefenum{TransactionCollectionSet,TransactionCollectionIncompatible,TransactionCollectionAlreadySet}ETransactionSetResult;typedefenum{TransactionOrderFirst,TransactionOrderLast}ETransactionDependentOrder;[async_uuid(5200cad2-8198-4c2a-98d8-f2cdfb0ab311),]interfaceIImgTransactionDependentItem:IUnknown{HRESULTCommit(void);HRESULTRevert(void);}[async_uuid(67ea48a1-7853-4a5c-862d-8af843855e23),]interfaceIImgBatchTransaction:IUnknown{HRESULTGetTransactionalCollection(GUID*pCollectionID,[out]IUnknown**ppIUnknown);HRESULTSetTransactionalCollection([in]IImgTransactionDependentItem*pITransCollection,[in]REFGUIDcollectionID,[out]ETransactionSetResult*peSetResult,[out]IUnknown**ppIResultingCollection);HRESULTInsertDependentAction([in]IImgTransactionDependentItem*pIDependent,[in]ETransactionDependentOrdereTransactionOrder);HRESULTCommit(void);HRESULTRevert(void);}注意,如果調(diào)用者或?qū)崿F(xiàn)者想要使用異步調(diào)用機制,則所有接口都使用COM異步調(diào)用模式。如果不是,則它們?nèi)钥蓪涌谶M(jìn)行同步調(diào)用,或?qū)崿F(xiàn)同步事務(wù)從屬動作。想要實現(xiàn)存儲或事務(wù)從屬項目就必須實現(xiàn)IImgTransactionDependentItem接口。此接口有兩個方法,Commit(提交)或Revert(反轉(zhuǎn))。存儲可以不能提交(但不可以不能反轉(zhuǎn)),而任何其它從屬項目必須總能成功執(zhí)行其Commit和Revert方法。每個事務(wù)可具有恰好一個存儲。當(dāng)前存儲及其存儲GUID可用GetTransactionalCollection方法檢索。如果調(diào)用者想要設(shè)置事務(wù)式存儲,則使用SetTransactionalCollection調(diào)用。因為事務(wù)是多線程的接口,所以SetTransactionalCollection同時取GUID和要被設(shè)置的集合,并且它返回現(xiàn)有的集合(若有)。有三種情形(如ETransactionSetResult返回參數(shù)所示)?!な聞?wù)當(dāng)前不具有相關(guān)聯(lián)的存儲對象。在此情形中,返回將是TransactionCollectionSet,且傳入的集合將變?yōu)榕c該事務(wù)相關(guān)聯(lián)的存儲。·事務(wù)當(dāng)前具有存儲對象,但它具有和你正在指定的相同的GUID。在此情形中,事務(wù)對象將把現(xiàn)有集合返回給調(diào)用者。調(diào)用者應(yīng)釋放它們先前的集合并用當(dāng)前在事務(wù)中的持久存儲來繼續(xù)該調(diào)用?!な聞?wù)當(dāng)前具有存儲對象,并且它是不同的存儲(它具有不同的存儲GUID)。在此情形中,事務(wù)對象將返回TransactionCollectionIncompatible。調(diào)用者通常將在這個點上未能通過操作。(這將使事務(wù)反轉(zhuǎn))。因為事務(wù)協(xié)調(diào)器無法知道到存儲對象的接口(它可以是從事務(wù)式文件系統(tǒng)到SQL數(shù)據(jù)庫的任何事物),所以這作為它們可經(jīng)由QueryInterface從其檢索實際存儲接口的IUnknown被返回給調(diào)用者。存儲必須實現(xiàn)IImgTransactionDependentItem,以使事務(wù)對象可正確地提交或反轉(zhuǎn)對存儲的改變。事務(wù)從屬項目在兩個階段被提交或反轉(zhuǎn)。這是經(jīng)由TransactionOrderFirst和TransactionOrderLast參數(shù)向InsertDependentAction指定的。依靠CAS進(jìn)行鎖定的事務(wù)應(yīng)僅使用TransactionOrderFirst,因為CAS使用TransactionOrderLast的從屬項目來確保對象鎖在協(xié)調(diào)事務(wù)被提交或反轉(zhuǎn)以后被釋放。工作流程CDI接口在相當(dāng)程度上是異步的。因此,可在單個線程上完成單個操作,或可在多個線程上完成單個操作。較少使用異步編程的系統(tǒng)??蓪顟B(tài)與線程相關(guān)聯(lián),例如,線程可具有相關(guān)聯(lián)的事務(wù),該事務(wù)一旦開始,就總是被蘊含在來自該線程的任何方法問題上。在CDI中,工作流程的概念取代了線程的這個一般概念。工作流程總是準(zhǔn)確地對應(yīng)于用戶所提交的批次。用戶不創(chuàng)建工作流程。它是在新的批次被發(fā)布時由CDI自動創(chuàng)建的。如果出于其自己的目的有所需要的話,服務(wù)器插件即可從頭創(chuàng)建工作流程。工作流程還提供對創(chuàng)建新的異步工作項目、以及將其與工作流程相關(guān)聯(lián)、并進(jìn)而與發(fā)起批次相關(guān)聯(lián)的支持。當(dāng)該批次被取消,工作流程即被取消,進(jìn)而該工作流程上的所有項目都被要求取消。使用此機制導(dǎo)致CDI無須在每個接口上都支持顯式的取消方法,該方法改為接收工作流程。工作流程接口如下所示。typedefenum{WorkFlowIsRunning,WorkFlowIsShutdown}EImgWorkFlowState;typedefenum{ExecuteNormal,ExecuteLongFunction,ExecuteIOThread}EImgWorkItemExecutionFlags;[object,uuid(cdeaa3da-a58f-462c-a186-f4e462f0f74c),local,helpstring("Serversideitemcompletioninterface."),pointer_default(ref)]interfaceIImgWorkItemControl:IUnknown{HANDLEWaitHandle(void);}interfaceIImgWorkItem:IUnknown{HRESULTRun(void);HRESULTNotifyCancel(void);}interfaceIImgWorkFlow:IUnknown{////如果請求控制,則可在稍后刪除該項目。這導(dǎo)致取消被發(fā)送到該工作項目。該工作項目必須//自發(fā)地終止。如果請求工作流程狀態(tài),則在該工作流程已被關(guān)閉的情況下,該項目將不會被//排隊,而該流程的狀態(tài)將被返回,否則調(diào)用將失敗。//HRESULTAddItem([in]IImgWorkItem*pIWorkItem,[in]EImgWorkItemExecutionFlagsFlags,[out,unique]IImgWorkItemControl**ppIItemControl,[out,unique]EImgWorkFlowState*peWorkFlowState);HRESULTAddWaitableItem([in]IImgWorkItem*pIWorkItem,[in]EImgWorkItemExecutionFlagsFlags,[out]IImgWorkItemControl**ppIItemControl,[out,unique]EImgWorkFlowState*peWorkFlowState);HRESULTAddDependentItem([in]IImgWorkItem*pIWorkItem,[out]IImgWorkItemControl**ppIItemControl,[out,unique]EImgWorkFlowState*peWorkFlowState);HRESULTShutdown(void);HRESULTAddToken([in]REFGUIDGuid);HRESULTFindToken([in]REFGUIDGuid,[out]BOOL*pbFound);HRESULTDeleteToken([in]REFGUIDGuid);HRESULTCreateNewScope([out]IImgWorkFlow**ppIWorkFlow);HRESULTCreateTransaction([out]IImgBatchTransaction**ppIBatchTransaction,[out]EImgBatchTransactionCreation*peBatchTransactionCreation);HRESULTGetBatchTransaction([out]IImgBatchTransaction**ppIBatchTransaction);HRESULTInsertTransactionalCollection([in]IUnknown*pITransCollection,[in]REFGUIDcollectionID,[out]IUnknown**ppISetTransCollection);HRESULTGetTransactionalCollection([out]IUnknown**ppITransCollection,[out]GUID*pCollectionID);}interfaceIImgCommonDataServer:IImgCommonData{HRESULTGetNewWorkFlow([out]IImgWorkFlow**ppIWorkFlow);}我們將把討論集中在工作流程所提供的以下服務(wù)上工作項目、令牌、范圍以及事務(wù)。事務(wù)在上文中被獨立討論,但工作流程對它們有一些特殊處理。工作項目為了實現(xiàn)工作項目,調(diào)用者必須實現(xiàn)IImgWorkItem接口。當(dāng)工作項目執(zhí)行時,在該接口上調(diào)用Run(運行)方法,而如果工作流程被取消,則Cancel(取消)方法被調(diào)用。有三種基本類型的工作項目·普通工作項目,用“AddWorkItem”創(chuàng)建。只要有充分的資源可用,這種工作項目即會運行。和所有工作項目一樣,調(diào)用者可通過工作項目標(biāo)志來指定哪種工作項目正在運行?!た傻却ぷ黜椖?,用“AddWaitableItem”創(chuàng)建??傻却ぷ黜椖繉⒃谄湎嚓P(guān)聯(lián)的事件被通知時運行。·從屬工作項目,用“AddDependentItem”創(chuàng)建。如果工作流程被取消,則從屬工作項目不被運行,但其“Cancel”方法被調(diào)用。這允許調(diào)用者使用不同的異步方法(例如,它們可調(diào)用帶有重疊結(jié)構(gòu)的ReadFile),但仍從原始工作流程接收取消通知。IImgWorkItemControl接口實現(xiàn)兩個目的——它允許可等待工作項目返回可被設(shè)置以觸發(fā)該工作項目的事件句柄。它還允許調(diào)用者通過釋放接口來取消特定工作項目。在此情形中,取消調(diào)用總是異步的,即,向工作項目通知取消,但該接口上的Release(釋放)調(diào)用不等待取消完成。這與工作流程上的Shutdown(關(guān)閉)方法的行為不一樣。關(guān)閉方法同步地等待工作流程中的所有工作項目被取消。令牌令牌被用來標(biāo)記工作流程上的特定狀態(tài)。它們旨在被用來防止實現(xiàn)截取時的無窮遞歸。即,特定類型的截取可將令牌添加到工作流程中,然后防止該類截取再次發(fā)生。令牌是GUID——令牌可被添加到工作流程中,可在工作流程中找到,并可從工作流程中移除。事務(wù)一個工作流程恰好可具有一個事務(wù)。工作流程是可從其創(chuàng)建事務(wù)的唯一接口。工作流程提供若干用戶處理當(dāng)前事務(wù)的幫助程序方法。·CreateTransaction創(chuàng)建事務(wù),并將其與當(dāng)前工作流程相關(guān)聯(lián)。如果事務(wù)已經(jīng)存在,則這被認(rèn)為是良性的,當(dāng)前事務(wù)被返回(調(diào)用者可推論這是通過EImgBatchTransactionCreation返回發(fā)生的)?!etBatchTransaction返回當(dāng)前與工作流程相關(guān)聯(lián)的批次事務(wù),若其存在的話。如果不存在,則它返回NULL?!nsertTransactionalCollection將集合插入到與工作流程相關(guān)聯(lián)的事務(wù)中。被插入的集合或現(xiàn)有的集合經(jīng)由被返回的ppISetTransCollection返回。如果這些集合是不兼容的(它們使用不同的GUID),則調(diào)用失敗?!etTransactionalCollection檢索與和工作流相關(guān)聯(lián)的事務(wù)相關(guān)聯(lián)的事務(wù)式集合。范圍被界定的工作流程一工作流程可包含其它工作流程。當(dāng)一工作流程的范圍被界定在另一工作流程內(nèi)時,它自動從其父工作流程繼承所有工作項目和令牌。它還從父工作流程繼承正在進(jìn)行中的任何事務(wù)。界定工作流程的范圍允許兩類主要的功能·父工作流程中的令牌不能被刪除。這允許工作流程中的令牌集被“鎖定”,直至工作流程調(diào)用遞歸退回到調(diào)用者。這是有用的,因為它可避免截取器不慎移除它不應(yīng)移除的令牌?!碜杂脩舻姆鞘聞?wù)式請求可要求事務(wù),以便作為實現(xiàn)細(xì)節(jié)被執(zhí)行。例如,刪除請求可要求若干子對象也被刪除。因為原始的批次可能包含不應(yīng)或不能被事務(wù)化的其它項目,所以我們不會向把事務(wù)添加到調(diào)用者所創(chuàng)建的工作流程中。解決方案是產(chǎn)生范圍被界定在第一個工作流程內(nèi)的工作流程,然后將事務(wù)與內(nèi)部的工作流程相關(guān)聯(lián)。這允許對任何工作項目的取消請求被保持,還允許原始工作流程上的任何令牌被保留,而無需使原始工作流程事務(wù)化。服務(wù)器方的通知CDI提供對插件集合的支持是希望支持通知。這允許通知通道同時從遠(yuǎn)程集合和本地(進(jìn)程內(nèi)或沙箱的)集合檢索數(shù)據(jù),并且仍然代表客戶機一致地處理通知通道。CAS為特定對象上的通知提供附加支持(諸如通過其鎖定基礎(chǔ)結(jié)構(gòu)確保通知被正確地串行化)。每個批處理集合都被給予一個IImgNotificationDataServer接口,它被用來將數(shù)據(jù)推入對應(yīng)于每個通知通道的客戶機集合。CDI本身維護(hù)客戶機集合以及通知的其它基礎(chǔ)結(jié)構(gòu)。typedefenum{ImgNotificationCollectFieldHistory,ImgNotificationDoNotCollectFieldHistory}EImgNotificationFieldOptions;typedefenum{NotifyAddNewObject,NotifyAddMatchedFilter}EImgNotifyAddReason;typedefenum{NotifyRemoveDeletedObject,NotifyRemoveDoesNotMatchFilter}EImgNotifyRemoveReason;typedefenum{NotifyUpdatePopulate,NotifyUpdate}EImgNotifyUpdateReason;interfaceIImgNotificationChannelShutdown:IUnknown{voidShutdownChannel(void);}interfaceIImgPushNotifyDataThroughChannel:IUnknown{HRESULTSendChangeDataNotify([in]EImgNotificationFieldOptionsfieldOption,[in]constImgVariant*pVariantData,[in]ULONGMapIndex,[in]IImgCanonicalName*objectID);HRESULTSendAddObjectNotify([in]EImgNotifyAddReasonreason,[in]IImgCanonicalName*objectID);HRESULTSendRemoveObjectNotify([in]EImgNotifyRemoveReasonreason,[in]IImgCanonicalName*objectID);HRESULTSendDone([in]EImgNotifyUpdateReasonreason);}interfaceIImgNotificationDataServer:IUnknown{HRESULTRegisterShutdown([in]IImgNotificationChannelShutdown*pINotifyChannelShutdown);HRESULTCreateNotificationObject([out]IImgPushNotifyDataThroughChannel**ppPushNotifyData);voidSendFailure([in]HRESULTErrorCode,[in,unique]IImgErrorInfo*pIErrorInfo);}通知數(shù)據(jù)服務(wù)器結(jié)構(gòu)公開三個方法·RegisterShutdown-此方法允許調(diào)用者注冊對正被關(guān)閉的通道的關(guān)注。例如,遠(yuǎn)程訪問適配器可能需要知道要在客戶機通知通道被銷毀時也要銷毀它自己的通知通道?!reateNotificationObject-此方法創(chuàng)建將數(shù)據(jù)推到通知通道中必須使用的新的通知接口。每個IImgPushNotifyDataThroughChannel實例都不是線程安全的。系統(tǒng)提供通過IImgPushNotifyDataThroughChannel實例發(fā)送的任何改變被作為一個組發(fā)送或全部不被發(fā)送的保證。·SendFailure-可能發(fā)生阻礙通知被通過通道發(fā)送的致命錯誤。在此情形中,SendFailure方法可被調(diào)用。它確保將銷毀通道。它還將以盡力服務(wù)方式將出錯信息發(fā)送給調(diào)用者。將通知數(shù)據(jù)推入通道接口具有以下方法·SendAddObjectNofity-此方法告訴通道新的通知對象已被添加。該對象或可因為其剛被創(chuàng)建而被添加,或可具有已改變的狀態(tài)來匹配查詢過濾器。·SendRemoveObjectNotify-此方法告訴通道對象真的已被刪除,或它不再匹配查詢過濾器并因此被從客戶機集合中邏輯地移除?!endChangeDataNotify-此方法將單個字段信息沿通道向下發(fā)送到客戶機。映射索引是客戶機經(jīng)注冊的類描述中的字段的索引。所發(fā)送的每個改變可具有兩個行為中的一個。如果改變被緩沖在系統(tǒng)中的某個地方,且發(fā)生對同一字段的另一個改變,則新的字段值起效。這具有將任何被緩沖的通知數(shù)據(jù)所需的存儲最小化的優(yōu)點。或者,每個改變都可以是顯著的,在此情形中,調(diào)用者可請求保持每個改變的歷史?!endDone-這完成已被發(fā)送到IImgPushNotifyData接口的改變。或者通知的初始數(shù)據(jù)被發(fā)送,在此情形中可使用NotifyUpdatePopulate變體,或者這是關(guān)于對象狀態(tài)中的后續(xù)改變的通知,在此情形中可指定NotifyUpdate。友好名稱解析插件插件批處理集合用來插入到規(guī)范名稱空間中的機制在以上題為“插件接口”的章節(jié)中描述。基本上,每個集合都由GUID標(biāo)識。如果批處理集合還想支持友好名稱,則它必須注冊友好名稱解析處理器。這在可能的情況下將被請求的類的友好名稱轉(zhuǎn)換為規(guī)范名稱。以注冊普通插件的相同方式向CDI注冊友好名稱解析器,不同之處在于使用友好名稱類來代替集合GUID,并改為使用不同的類工廠和接口。類工廠和插件接口如下所示。interfaceIImgClassNameResolvingHandlerFactory:IUnknown{HRESULTLockServer([in]BOOLfLock);HRESULTCreateInstance([in]IImgCommonData*pICommonData,[in,unique]IXMLDOMNode*pXmlInitData,[in]REFIIDriid,[out]void**ppvObj);}interfaceIImgClassNameResolvingHandler:IUnknown{HRESULTBeginResolveName([in,string]constwchar_t*pszName,[in,string]constwchar_t*pszClass,[in,unique]IImgServerItemCompletion*pICompletion,[out,unique]void**ppContext);HRESULTEndResolveName([in]void*pContext,[out]IImgCanonicalNameIterator**ppIterator);}當(dāng)客戶機請求名稱解析時,如果友好名稱解析器不能在高速緩存中找到該名稱,則對應(yīng)于該類的每個已注冊的插件的名稱解析處理器被調(diào)用(以并行調(diào)用的方式)。每個名稱解析器都試圖解析該名稱,當(dāng)名稱解析結(jié)束時,解析器調(diào)用IImgServerItemCompletion接口上的Done。接著名稱解析器將以BeginResolveName返回的相同上下文調(diào)用EndResolveName。然后名稱解析器返回IImgCanonicalName迭代器,它包含名稱解析器確定為對應(yīng)于該友好名稱的任何規(guī)范名稱。注意,名稱解析器插件通常將對CDI接口使用獲取、查詢或命令來執(zhí)行其名稱解析。因此,實現(xiàn)異步接口通常不會有很大問題,因為它將進(jìn)而被另一個異步接口調(diào)用。為了避免調(diào)用者不得不為每個查詢集合實現(xiàn)一個IImgCanonicalName迭代器,提供聚集規(guī)范名稱并可從其返回迭代器實例的集合接口。此接口如下所示。interfaceIImgCommonData:IUnknown{HRESULTCreateCanonicalNameCollection([out]IImgCanonicalNameCollection**ppINameCollection);}interfaceIImgCanonicalNameCollection:IUnknown{HRESULTAddCanonicalName([in]IImgCanonicalName*pIImgCanonicalName);HRESULTMerge([in]IImgCanonicalNameIterator*pIImgCanonicalNameEnum);HRESULTGetIterator([out]IImgCanonicalNameIterator**ppIterator);}集合適配器服務(wù)在所示出并描述的實施例中,IImgBatchCollection接口看似實現(xiàn)起來很復(fù)雜。調(diào)用者必須遍歷每個批次項目,將其解碼,并決定如何響應(yīng)于該項目。一般而言,集合想要訪問批次的唯一原因是要保持該批次以進(jìn)行跨越機器或進(jìn)程邊界的發(fā)送。在批次實際上與被加載到持久存儲及從持久存儲加載的一組對象交互時,這是需要插件處理的很大復(fù)雜性。為此原因,提供了集合適配器服務(wù)。集合適配器服務(wù)提供以下功能·它從一組插件集合檢索對象?!に鼘嵗膶ο蟾咚倬彺?,并在它們沒有被使用的時候刷新它們?!にㄟ^類型映射管理客戶機對象到服務(wù)器對象的綁定。·它協(xié)調(diào)兼容集合之間的事務(wù)?!にY(jié)合事務(wù)管理對象鎖?!に芾硗胶彤惒綄ο??!にc查詢編譯器交互以實現(xiàn)對象過濾器?!にㄟ^動態(tài)地選擇要串行還是并行地執(zhí)行調(diào)用來最好地利用資源?!にㄟ^最優(yōu)的鎖定方案維護(hù)對象的并發(fā)?!に幚韺ο蟾淖兺ㄖ?。如果基本CDI是將各插件粘合在一起的膠水,則集合適配器服務(wù)負(fù)責(zé)確保能盡可能簡單地實現(xiàn)智能的、異步的、高性能的插件。根據(jù)一個實施例,在圖14中示出集合適配器服務(wù)模型。給定的CAS實例可有多個對象集合被插入其中。每個對象集合都支持單個類名,例如,“Printers”,且給定對象集合中的所有對象都是同類的。因此,它們可由表達(dá)給定服務(wù)器對象實現(xiàn)的所有屬性和命令的單個類描述來描述。集合適配器服務(wù)使用服務(wù)器類描述在客戶機和服務(wù)器對象之間傳輸數(shù)據(jù)和執(zhí)行對象命令。服務(wù)器中的每個對象都經(jīng)由其IImgObject接口實現(xiàn)某些基本功能。IImgCollectionAdapter具有以下接口interfaceIImgCollectionAdapter:IImgBatchCollection{HRESULTInitialize([in]IImgCommonDataServer*pICommonDataServer);HRESULTRegisterObjectCollection([in]IImgObjectCollection*pIObjectCollection);}客戶機通過調(diào)用其IImgBatchCollectionFactory::CreateInstance方法中的“CoCreateInstance”將集合適配器實例化。它調(diào)用IImgCollectionAdapter::Initialize并將向其傳遞的IImgCommonDataServer接口傳遞給該方法。然后它通過RegisterObjectCollection調(diào)用注冊其每一個對象集合。IImgObjectCollection具有以下方法interfaceIImgObjectCollection:IUnknown{////如果覆蓋之下的此對象不支持事務(wù),則此調(diào)用應(yīng)以E_NOTIMPL失敗。//HRESULTGetTransactionalCollectionData([out]IUnknown**ppITransactionalCollection,[out]ETransactionSupport*peTransactionSupport,[out]GUID*pCollectionID);HRESULTGetCollectionData([out]IImgImmutableString**ppIObjectClass,[out]GUID*pObjectID,[out]ImgServerClassDescription*pServerClassDescription);HRESULTBeginGet([in]IImgWorkFlow*pIWorkFlow,[in]IImgServerItemCompletion*pIItemCompletion,[in]IImgImmutableString*pIObjectName,[out]void**ppContext);HRESULTEndGet([in,unique]void*pContext,[out]IImgObject**ppIObject);HRESULTBeginEnum([in]IImgWorkFlow*pIWorkFlow,[in]IImgServerItemCompletion*pIItemCompletion,[in]IImgCanonicalName*pIObjectBase,[in]IImgImmutableString*pIObjectBaseClass,[in]IImgImmutableString*pIQueryString,[out]void**ppContext);HRESULTEndEnum([in,unique]void*pContext,[out]IImgObjectIterator**ppIObjects);HRESULTShutdown([in]EImgShutdownReasoneReason);}GetTransactionCollectionData調(diào)用返回集合如何事務(wù),集合可不支持任何事務(wù),可支持事務(wù)作為從屬項目(這可由瞬態(tài)集合支持),或可通過返回依賴于底層存儲系統(tǒng)的自定義事務(wù)接口以及唯一地標(biāo)識事務(wù)可成功的范圍的ID來支持事務(wù)。GetCollectionData調(diào)用返回對象類名、優(yōu)化的類型映射綁定中使用的ObjectId、以及描述每個對象的服務(wù)器類描述。其余調(diào)用,BeginGet和EndGet以及BeginEnum/EndEnum允許從集合檢索對象。Shutdown(關(guān)閉)方法在IImgBatchCollection::Shutdown方法被調(diào)用時由CAS調(diào)用。CAS所執(zhí)行的很可能消耗大量時間的任何調(diào)用將表現(xiàn)為Begin/End對的形式。每個Begin調(diào)用取IImgServerItemCompletion接口,并允許通過ppContext參數(shù)返回上下文。CAS向接口的實現(xiàn)者提供以下保證·如果Begin(開始)調(diào)用失敗,則End(結(jié)束)調(diào)用將不會被調(diào)用。·如果Begin調(diào)用成功,則保證End調(diào)用會被調(diào)用?!ぴ贗ImgServerItemCompletion::Done方法被調(diào)用以前End調(diào)用將不會被調(diào)用?!ぴ贐egin方法返回以前End調(diào)用將不會被調(diào)用?!⑾駿nd調(diào)用傳遞在Begin調(diào)用中所返回的上下文。這些保證允許Begin方法通過在Beging方法內(nèi)調(diào)用Done來實現(xiàn)同步調(diào)用。它所執(zhí)行的任何IO綁定的操作應(yīng)或者在另一個線程中被執(zhí)行(較佳的是與其它操作整合),或應(yīng)進(jìn)而被實現(xiàn)為異步調(diào)用。當(dāng)異步項目完成時,則IImgServerItemCompletion::Done方法應(yīng)被調(diào)用。如果Begin方法需要跟蹤專屬于該調(diào)用的任何狀態(tài),則它可在ppContext參數(shù)中被返回。因為CAS保證End調(diào)用會被執(zhí)行,所以上下文總是能夠被釋放。CAS使用以下用于調(diào)度調(diào)用的機制·如果調(diào)用是同步的(在Begin方法內(nèi)調(diào)用了Done),且調(diào)用者請求并行執(zhí)行,則假定該方法的執(zhí)行是CPU綁定的。因此,下一個調(diào)用將被串行化在第一個調(diào)用上。如果調(diào)用失敗,則結(jié)果被記錄,但所有后續(xù)調(diào)用仍被執(zhí)行?!と绻{(diào)用是異步的,并且客戶機請求并行執(zhí)行,則在原始線程中下一個“Begin”方法被立即調(diào)用?!と绻{(diào)用是異步的,并且客戶機請求串行或事務(wù)式語義,則工作的其余部分將在調(diào)用IImgServerItemCompletion::Done方法的同一線程中被執(zhí)行。這些規(guī)則意味著CAS的客戶機集合或?qū)ο蟊仨毚_保IO綁定操作是在異步調(diào)用模式中執(zhí)行的,否則它可能會阻礙其它工作項目的并行執(zhí)行。對象具有以下接口interfaceIImgObject:IUnknown{HRESULTInitialize([in]IImgObjectHandler*pIChangeHandler,[out]ULONG*pCallFilterFlags);HRESULTGetRealObjectAddress([out]void**ppObject);HRESULTBeginGet([in]IImgWorkFlow*pIWorkFlow,[in]IImgServerItemCompletion*pICallCompletion,[in]ULONGcTags,[in,size_is(cTags)]ULONG_PTR*aTags,[out]void**ppContext);HRESULTEndGet([in,unique]void*pContext);HRESULTCloneObject([out]IImgObject**ppISettableObject);HRESULTBeginSet([in]IImgWorkFlow*pIWorkFlow,[in]IImgServerItemCompletion*pICallCompletion,[in,unique]IImgBatchTransaction*pIBatchTransaction,[in,unique]IUnknown*pITransactionalCollection,[in]ULONGcTags,ULONG_PTR*aTags,[out]void**ppContext);HRESULTEndSet([in,unique]void*pContext);}要被實現(xiàn)的方法如下·Initialize(初始化)調(diào)用在對象首次從集合被返回給CAS時由CAS調(diào)用。它向該對象傳遞允許該對象將其自身刪除、將其自己鎖定、與事務(wù)交互和向系統(tǒng)的其余部分發(fā)送改變通知的處理器接口。它還可返回調(diào)用過濾器。調(diào)用過濾器指示該對象是否支持部分實例化(在此情形中,在從其讀出任何數(shù)據(jù)以前將對其調(diào)用BeginGet/EndGet方法)。它還通過寫出某些字段來指示它是否支持將對象持久化。在此情形中,BeginSet/EndSet方法將被調(diào)用,以準(zhǔn)確地指定調(diào)用者在設(shè)置中指定了哪些屬性?!etRealObjectAddress返回ImgServerClassDescription訪問器所相對于的對象地址。這是必要的,因為如果對象是使用多繼承來實現(xiàn)的,則IImgObject接口地址不一定和實際的對象地址相同。·BeginGet/EndGet-這些方法僅在對象在其調(diào)用過濾器中指示它支持部分對象的情況下被調(diào)用。將向?qū)ο髠鬟f指示優(yōu)化映射要讀出哪些字段的標(biāo)記。對象可在其首次從持久存儲實例化以后使用此標(biāo)記來獲取重量級字段。如果對象執(zhí)行此操作并且該調(diào)用是IO綁定的(幾乎總是這樣),則它必須使用異步調(diào)用模式?!loneObject-CAS假定對象是以不可變的方式實現(xiàn)的。這允許在從對象讀取數(shù)據(jù)的同時,該對象保持不被鎖定的狀態(tài)。它簡化了事務(wù),因為可將對象保持在被復(fù)制的狀態(tài)直至事務(wù)提交。因此,在設(shè)置發(fā)生以前,對象將被要求克隆其自身。對象必須以不可變的方式來編碼才能與CAS兼容?!eginSet/EndSet-在設(shè)置中,當(dāng)對象已被克隆以后這一對方法被調(diào)用,并且其訪問器被用來改變其狀態(tài)。對象可在此調(diào)用中確認(rèn)其新狀態(tài)是有效的。如果在調(diào)用過濾器中對象請求該新狀態(tài),則它將被告知在設(shè)置發(fā)生時客戶機指定了哪些字段。對象處理器對象處理器是由CAS傳遞給每個對象以允許該對象以各種方式與CAS交互的接口。CAS中每個被高速緩存的對象有恰好一個對象處理器的實例。IImgObjectHandler還公開對應(yīng)于每個對象的異步鎖。此鎖被CAS用來邏輯地將就狀態(tài)改變而對對象的訪問串行化,這些狀態(tài)改變包括事務(wù)和改變通知。對象上的數(shù)種動作要求對象被鎖定。對象處理器接口強制執(zhí)行此語義。對象處理器接口如下所示interfaceIImgObjectHandler:IUnknown{HRESULTGetObjectLock([out]IImgAsyncLock**ppIObjectLock);HRESULTDeleteObject([in]ImgLockContextlockLogicalID);HRESULTCurrentObject([in]ImgLockContextlockLogicalID,[out]IImgObject**ppIObject);HRESULTReplaceObject([in]ImgLockContextlockLogicalID,[in]IImgObject*pIObject);HRESULTGetChangeHandler([in]ImgLockContextlockLogicalID,[out]IImgObjectChangeHandler**ppIChangeHandler);HRESULTHoldObjectInCache(void);HRESULTReleaseObjectFromCache(void);}對象異步鎖一個重要的方法是GetObjectLock,它允許調(diào)用者檢索與對象相關(guān)聯(lián)的鎖。所返回的鎖是支持事務(wù)式鎖定的異步鎖。鎖及相關(guān)聯(lián)的語義由CAS使用,且相同的語義應(yīng)由其它調(diào)用者使用。接口如下所示。interfaceIImgLockEntry:IUnknown{HRESULTEnterLock([in]INT_PTRentryContext,[in]ImgLockContextlogicalID);HRESULTNotifyCancel(void);}interfaceIImgLockSequence:IUnknown{////如果變量無效,則這只可能失敗。一旦獲得了序列,即確保能進(jìn)入對象。序列必須被串行地獲得,但不//必在同一個線程中。//HRESULTAcquireLock([in]INT_PTRentryContext);HRESULTTryAcquireLock([out]BOOL*pbAcquired,[out]ImgLockContext*pLogicalID);HRESULTIsCancelled([out]BOOL*pbCancelled);}interfaceIImgAsyncLock:IUnknown{HRESULTGetLockSequence([in]IImgWorkFlow*pIWorkFlow,[in]IImgLockEntry*pIEntryInterface,[out]IImgLockSequence**ppILockSequence,[out,unique]EImgWorkFlowState*peWorkFlowState);HRESULTReleaseLock([in]ImgLockContextlogicalID);HRESULTAddTransactionToLock([in]IImgBatchTransaction*pIBatchTransaction,[out]BOOL*pbTransactionAdded);HRESULTWaitForTransactionToFinish([in]IImgWorkFlow*pIWorkFlow,[in]IImgServerItemCompletion*pIItemCompletion,[out,unique]EImgWorkFlowState*peWorkFlowState);};鎖是異步的,即當(dāng)可獲得該鎖時它進(jìn)行回調(diào)。這是有意的設(shè)計選擇,它提供以下能力·試圖獲得鎖的工作流程可被取消。因為鎖接口是異步的,所以可通知調(diào)用者鎖獲得嘗試被取消?!ひ驗殒i被用來將諸事務(wù)上的對象訪問串行化,并且因為事務(wù)可能必須獲得許多對象并且通常必須將狀態(tài)寫到存儲中,所以對象鎖可能要被保持很長一段時間。因此,任何鎖訪問都可能等待IO綁定的操作。使用異步鎖允許為另一個CPU綁定的操作重用該線程,而不是必須等待IO完成。注意,CAS對獲取/查詢和命令不使用對象鎖。這意味著盡管事務(wù)可能邏輯上持有一操作,但是它僅將設(shè)置和通知串行化。如果調(diào)用者希望一命令是事務(wù)性的,則它們必須自己創(chuàng)建該事務(wù)并獲得對象鎖。想要獲得鎖的調(diào)用者必須實現(xiàn)IImgLockEntry接口。此接口有兩個方法,EnterLock和NotifyCancel。EnterLock是在調(diào)用者已獲得鎖時被調(diào)用的。ImgLockContext被傳遞給EnterLock函數(shù)。這一鎖上下文與該鎖的特定獲得被準(zhǔn)確地相關(guān)聯(lián),并且必須在該鎖被釋放時被移交給鎖接口。這實現(xiàn)兩個目的·如果另一個調(diào)用者錯誤地試圖在沒有獲得鎖的情況下釋放鎖,則釋放無效?!ゆi必須被保持這一事實可由其它接口通過請求提供鎖上下文而在語義上表達(dá)。這還可在執(zhí)行相關(guān)聯(lián)的動作以前檢查鎖確實被保持。此外,如果調(diào)用者在其上獲得鎖的工作流被取消,則其接口上的NotifyCancel方法將被調(diào)用。它們隨即可決定它們?nèi)员仨毇@得該鎖,還是要中止它們對該鎖的訪問。它們可通過釋放被返回的在其上它們調(diào)用了AcquireLock的鎖序列接口來取消它們對鎖的獲得。不希望發(fā)生調(diào)用者不能保證鎖能被獲得這樣的情況。例如,它們可能想要獲得鎖,遞增引用計數(shù),然后釋放該鎖。然后它們可對對象執(zhí)行某些動作,再次獲得該鎖,并遞減引用計數(shù)。如果它們不能為第二個操作獲得鎖,則引用計數(shù)將永遠(yuǎn)無法被正確遞減。調(diào)用者確保對鎖的訪問的能力是由IImgLockSequence接口提供的。一旦從鎖返回鎖序列,即可保證該鎖任何順序獲得和釋放都會成功。這能起效是因為作為實現(xiàn)細(xì)節(jié),IImgLockSequence接口是由保留足夠存儲因而總能夠獲得鎖的對象實現(xiàn)的。鎖和事務(wù)事務(wù)可能需要依次鎖定許多對象。這在一個以上事務(wù)之間有任何對鎖的循環(huán)獲得的情況下給系統(tǒng)帶來了死鎖的機會。兩個事務(wù)同時持有同一個鎖在語義上是不合法的,所以鎖提供了對事務(wù)的特殊支持。當(dāng)在設(shè)置屬性前鎖定對象時,這被CAS自動使用,并且它應(yīng)被想要實現(xiàn)事務(wù)式語義的任何對象使用。一個鎖每次只能恰好被一個事務(wù)持有。想要獲得鎖的事務(wù)使用AddTransactionToLock調(diào)用。如果已有事務(wù)持有該鎖,則該調(diào)用將在pbTransactionAdded參數(shù)中返回FALSE。然后在向調(diào)用者返回失敗以前,事務(wù)應(yīng)被反轉(zhuǎn)(這釋放當(dāng)前該事務(wù)所持有的任何鎖或資源)并等待現(xiàn)有事務(wù)完成。調(diào)用者調(diào)用WaitForTransactionToFinish來等待任何持有該鎖的事務(wù)完成(它們將被異步地通知)。如果沒有任何事務(wù)持有該鎖,則它們將立即回調(diào)。如果事務(wù)被提交或反轉(zhuǎn),則鎖將被自動與該事務(wù)解除關(guān)聯(lián)。調(diào)用者應(yīng)等待現(xiàn)有事務(wù)結(jié)束的原因是要保證如果調(diào)用者重試該操作,它們不會只是再次檢索原來的(未被改變的)對象狀態(tài),并相對于持有該鎖的事務(wù)進(jìn)行“旋轉(zhuǎn)”。CDI/CAS最優(yōu)鎖定模型CDI有意地不向客戶機公開任何鎖定構(gòu)造。這有以下幾個理由·每個鎖都不得不向服務(wù)器添加附加的上下文額外開銷,而這可由客戶機維護(hù)?!と绻蛻魴C進(jìn)入出錯狀態(tài)并抓住鎖不放,則它可能會損害服務(wù)器的操作?!榱颂幚聿会尫沛i的客戶機,必須向服務(wù)器添加手動開鎖機制。這是不然可被簡單地避免的額外的UI和維護(hù)。但是,服務(wù)器狀態(tài)被正確地維護(hù)并且“決斗管理員”問題被避免是合乎需要的。如果兩個管理員同時試圖重命名一打印機,我們可能想要確保一個重命名成功而另一個失敗。系統(tǒng)部分地通過事務(wù)用來獲得對象鎖的機制來維護(hù)這些語義。還通過給予每個對象一個“Object:LockId”屬性來進(jìn)行維護(hù)。簡言之,為了改變對象狀態(tài),還必須提供匹配當(dāng)前對象鎖ID的鎖ID。這表示在試圖改變對象以前是知道最后的對象狀態(tài)的。如果提供了不匹配的對象ID,則改變狀態(tài)的嘗試將會失敗。響應(yīng)于此,調(diào)用者必須重新獲取它們想要改變的屬性,并因此重新獲取鎖ID。良好編寫的客戶機然后將檢查這些屬性以確保它們想要實現(xiàn)的改變?nèi)匀皇怯幸饬x的,然后才再次嘗試該操作。對象改變處理器為了檢索對應(yīng)于對象的改變處理器,必須獲得對象鎖,然后必須調(diào)用該對象處理器上的GetChangeHandler方法。GetChangeHandler方法要求鎖上下文。對象可用來獲得改變處理器的其它機制是在設(shè)置期間將它作為參數(shù)被傳入到屬性訪問器。(在此情形中,CAS在為調(diào)用者設(shè)置任何對象屬性以前獲得對象鎖)。對象改變處理器接口如下所示。interfaceIImgObjectChangeHandler:IUnknown{HRESULTNotifyChange([in]ULONG_PTRtag);HRESULTNotifyChangeData([in]EImgNotificationFieldOptionsfieldOptions,[in]ULONG_PTRtag,[in]ImgVariant*data);HRESULTSendChanges(void);}CDI改變處理器接口已在上一節(jié)討論。該接口提供將改變沿特定通道向下發(fā)送的能力。CAS增加了正確地界定查詢范圍并處理特定對象中可能被關(guān)注的所有通道的能力。對象所必須做的僅僅是指示哪些屬性已改變。最簡單的機制是調(diào)用NotifyChange并傳遞對應(yīng)于已經(jīng)改變的字段的標(biāo)簽。CAS隨即將經(jīng)由屬性訪問器檢索對應(yīng)于該字段的數(shù)據(jù),并將屬性改變通知發(fā)送給所有關(guān)注該改變的通道。為了節(jié)省CAS檢索屬性的工作量,調(diào)用者還可經(jīng)由NotifyChangeData調(diào)用直接指定數(shù)據(jù)。最后,當(dāng)所有改變都已被聚集到改變處理器中時,它們可經(jīng)由SendChanges方法被發(fā)送。如果其中任何改變不能被發(fā)送,則CAS將銷毀所有可能以該對象為目標(biāo)的通知通道。IATL對改變通知的支持對象不難實現(xiàn)改變通知。為使之更加簡單,如果僅通過CDI屬性獲取或設(shè)置改變了對象的屬性,并且該屬性被實現(xiàn)為數(shù)據(jù)成員,則IATL將為之自動生成改變通知代碼。當(dāng)指定字段時,gNotify修改器只需在類型映射中被傳遞給Field(字段)函數(shù)。如下所示。classJob{public:IImgImmutableString*Name;};IMG_ATTR_TABLE_BEGIN(Job,Img::iatl::TypeMap)Type(L"Job.State"),Field(IMG_ATTR_FIELD(Name),gNotify),IMG_ATTR_TABLE_END這將為屬性自動構(gòu)建獲取和設(shè)置訪問器。如果該屬性改變,則該改變將被發(fā)送給由CAS提供給屬性訪問器的改變處理器。其余對象處理器函數(shù)DeleteObject(刪除對象)此函數(shù)從CAS的高速緩存中刪除對象。此函數(shù)還會向客戶機發(fā)送改變通知。對象必須被鎖定,且鎖上下文必須被提供才能刪除該對象。CurrentObject(當(dāng)前對象)CAS使用不可變的對象模型。當(dāng)對象被修改時,如果其狀態(tài)被改變,則它被克隆,然后被插入到高速緩存中。如果發(fā)生錯誤,則新對象被丟棄。此設(shè)計的值得關(guān)注的含義是,如果對象希望將改變通知作為異步事件的結(jié)果發(fā)送,或者它需要屬性獲取期間或命令期間對象最后的版本,則它不能知道它當(dāng)前持有的對象的實例是正確的實例。為處理此情況,對象處理器可檢索當(dāng)前對象實例。因為對象狀態(tài)改變受到對象鎖的保護(hù),所以必須在當(dāng)前對象可被有意義地檢索以前獲得鎖。HoldObjectInCache和ReleaseObjectFromCacheCAS通常在對象被丟棄以前將其高速緩存在存儲器中大約10秒鐘。對象可決定改為永久留存在高速緩存中,或者在另一個對象被高速緩存的同時保持被高速緩存。為處理此需要,可在對象處理器上調(diào)用HoldObjectInCache方法。當(dāng)被調(diào)用時,對象將被保持在高速緩存中,直至進(jìn)行了對應(yīng)的ReleaseObjectFromCache調(diào)用。HoldObjectInCache可被調(diào)用任意多次,只有在當(dāng)進(jìn)行了相同次數(shù)的對ReleaseObjectFromCache的調(diào)用時對象才會被釋放。僅可在對象已因為某些其它操作原因而被活動地保持在高速緩存中的情況下安全地調(diào)用HoldObjectInCache。否則,就可能有在正對HoldObjectInCache進(jìn)行調(diào)用的同時該對象正被從高速緩存釋放的競爭條件。這不會導(dǎo)致崩潰,但是很明顯,在此情形中HoldObjectInCache調(diào)用不能被優(yōu)先對待。保證HoldObjectInCache能成功的時間點是·在對該對象所支持的IImgObject接口的初始化調(diào)用期間。·在任何屬性獲取或設(shè)置或命令調(diào)用期間?!せ虍?dāng)調(diào)用者知道它們先前已經(jīng)發(fā)布過HoldObjectInCache調(diào)用時??蚣芴峁┑募螴ImgObjectCollection和IImgObject接口不是特別難以實現(xiàn),并且會有使用CAS的插件想要或需要同時實現(xiàn)這兩者的情形。例如,當(dāng)編寫經(jīng)由新的數(shù)據(jù)模型表示下級服務(wù)器上的對象的適配器時,會想要提供自己的IImgObjectCollection。但是,有很多情形中可使用標(biāo)準(zhǔn)框架提供的對象集合。這些在圖15中示出。各種框架提供的集合及其函數(shù)如下。存儲器內(nèi)集合提供沒有被持久化的對象的動態(tài)集合。此集合在由插件提供了要公開的若干實際的不可變對象(諸如過濾器工廠)時是很有用的。在諸如TS打印等情形中為輕量級不可持久化對象提供存儲時它也是有用的。持久對象集合服務(wù)是提供在持久存儲中將對象持久化的能力的集合??赡苡性S多存儲可在其中將對象持久化,包括注冊表、SQL數(shù)據(jù)庫或WinFS。每個存儲都具有其自己的持久對象集合服務(wù)實例。持久對象集合服務(wù)將為把對象狀態(tài)持久化到適當(dāng)?shù)拇鎯χ刑峁┲С帧K鼘⑹褂梅?wù)器類型映射(ImgServerClassDescription)來檢索必要的對象狀態(tài)以進(jìn)行存儲。此外,在可能的情況下,它將把查詢直接映射到由底層存儲所提供的查詢支持。通知填充程序集合如下工作。在許多情形中,系統(tǒng)將被橋接到對通知提供有限支持或不支持通知的下級系統(tǒng)。在此情形中,調(diào)用者需要枚舉所有對象,查看新對象何時到來或離開,并在有任何字段改變的情況下激發(fā)合適的通知。因為IImgObjectCollection接口是公開的,并且ImgServerClassDescription允許調(diào)用者訪問對象上的所有字段,所以將提供把此行為自動化的通用填充程序?qū)ο蠹稀_€可為只是不想添加額外數(shù)行代碼來支持通知的調(diào)用者使用此集合。但是,可為在改變時會自動生成通知的字段提供默認(rèn)實現(xiàn)。總而言之,該框架將提供若干固定對象集合,這將使大多數(shù)人無需實現(xiàn)自己的集合接口。適配器集合接口是可能的例外。提供填充程序集合是為了自動化從下級適配器的事件生成。IImgObject的IATL實現(xiàn)IImgObject也不是特別難實現(xiàn)的接口。為使編寫標(biāo)準(zhǔn)對象盡可能地簡單,IATL提供支持非部分對象實現(xiàn)的IImgObject的標(biāo)準(zhǔn)實現(xiàn)。其所實現(xiàn)的類如下·TServerObjectBase-提供IUnknown、Initialize、BeginGet/EndGet和BeginSet/EndSet的默認(rèn)實現(xiàn)。獲取和設(shè)置函數(shù)不執(zhí)行任何操作?!ServerObject-此模板通過基類模板化添加GetRealObjectAddress實現(xiàn)?!ServerDefaultCloneableObject-此模板添加CloneObject方法。調(diào)用者必須在其派生類中提供復(fù)制構(gòu)造函數(shù),并且必須或者不拋出異常、或者在出錯情況下拋出異常、或者在對象已被復(fù)制以后從其IsValid()方法返回錯誤?!IMCServerObject-此對象為存儲器內(nèi)集合實現(xiàn)BeginSet/EndSet方法對。托管對象IATL被設(shè)計成通過提供允許方法和字段通過CDI被表達(dá)為屬性并允許方法通過CDI被表達(dá)為命令的模板庫來對非托管的C++類提供自動化支持。保持在非托管空間中有許多好處,但是,系統(tǒng)也會想要為托管對象提供數(shù)據(jù)驅(qū)動的支持,特別是當(dāng)托管代碼在性能、強健性和設(shè)計穩(wěn)定性方面有所提高的情況下。因為CAS封裝大量重要功能,所以有執(zhí)行同樣任務(wù)的并行托管實現(xiàn)是不明智的。解決方案是使用托管元數(shù)據(jù)在非托管空間中創(chuàng)建ImgServerClassDescription,并用其來填充和維護(hù)影子非托管對象。圖16中示出根據(jù)一個實施例的解決方案。在此,來自托管對象的類元數(shù)據(jù)被映射到非托管空間中的ImgServerClassDescription。這個類描述使用可操縱影子非托管對象的訪問器。非托管對象中的每個屬性可被索引,并將對應(yīng)于托管對象中的一個屬性。托管對象將使用改變通知機制將異步改變傳播到影子非托管對象。每當(dāng)在非托管對象上發(fā)生設(shè)置時,這些屬性首先會被應(yīng)用于托管對象,然后托管對象的狀態(tài)將被復(fù)制回非托管對象。命令將被直接映射到托管對象上的方法調(diào)用。此機制的優(yōu)點是對象上最常用的操作獲取和查詢將完全在非托管影子對象上執(zhí)行。此外,非托管影子對象可由非托管持久對象集合服務(wù)存儲,并可被放在存儲器內(nèi)集合中。這還規(guī)避了原本執(zhí)行屬性獲取所需的緩慢的反射機制。對托管對象的改變可被約束到每個批處理動作有一個可相互操作的替換程序。因為這是在CAS之后發(fā)生,所以我們不能在整個批次被解釋以前對其進(jìn)行封送。此限制應(yīng)通過在查詢和獲取情形中完全避免托管路徑來抵消。示例性客戶機設(shè)備/打印服務(wù)器組件圖17示出一種示例性計算設(shè)備,它具有可在客戶機設(shè)備和打印系統(tǒng)中使用以實現(xiàn)上述實施例的組件。計算設(shè)備1742包括一個或多個處理器或處理單元1744、系統(tǒng)存儲器1746、以及將包括系統(tǒng)存儲器1746在內(nèi)的各個系統(tǒng)組件耦合到處理器1744的總線1748??偩€1748表示數(shù)種總線結(jié)構(gòu)中的任何一種或數(shù)種,包括存儲器總線或存儲器控制器、外圍總線、加速圖形端口、以及使用各種總線體系結(jié)構(gòu)中的任何一種的處理器或局部總線。系統(tǒng)存儲器1746包括只讀存儲器(ROM)1750和隨機存取存儲器(RAM)1752。包含諸如在啟動期間幫助在計算設(shè)備1742的各元件之間傳遞信息的基本例程的基本輸入/輸出系統(tǒng)(BIOS)1754被存儲在ROM1750中。計算設(shè)備1742還可包括用于讀或?qū)懹脖P(未示出)的硬盤驅(qū)動器1756,用于讀或?qū)懣梢苿哟疟P1760的磁盤驅(qū)動器1758、以及用于讀或?qū)懼T如CDROM或其它光介質(zhì)等可移動光盤1764的光盤驅(qū)動器1762。硬盤驅(qū)動器1756、磁盤驅(qū)動器1758和光盤驅(qū)動器1762由SCSI接口1766或某種其它適當(dāng)?shù)慕涌谶B接到總線1748。各驅(qū)動器及其相關(guān)聯(lián)的計算機可讀介質(zhì)為計算機1742提供計算機可讀指令、數(shù)據(jù)結(jié)構(gòu)、程序模塊或其它數(shù)據(jù)的非易失性存儲。盡管這里所描述的示例性環(huán)境使用硬盤、可移動磁盤1760和可移動光盤1764,但是本領(lǐng)域技術(shù)人員應(yīng)當(dāng)認(rèn)識到,在該示例性操作環(huán)境中還可使用可存儲可由計算機訪問的數(shù)據(jù)的其它類型的計算機可讀介質(zhì),諸如磁帶盒、閃存卡、數(shù)字視頻盤、隨機存取存儲器(RAM)、只讀存儲器(ROM)等等。若干程序模塊可被存儲在硬盤1756、磁盤1760、光盤1764、ROM1750或RAM1752上,包括操作系統(tǒng)1770、一個或多個應(yīng)用程序1772(諸如用戶代理或瀏覽器)、其它程序模塊1774、以及程序數(shù)據(jù)1776。用戶可通過諸如鍵盤1778和定位設(shè)備1780等輸入設(shè)備將命令和信息輸入到計算機1742中。其它輸入設(shè)備(未示出)可包括話筒、操縱桿、游戲墊、圓盤式衛(wèi)星天線、掃描儀等。這些及其它輸入設(shè)備通過被耦合到總線1748的接口1782連接到處理單元1744。監(jiān)視器1784或其它類型的顯示設(shè)備也經(jīng)由諸如視頻適配器1786等接口連接到總線1748。除了監(jiān)視器以外,個人計算機通常還包括諸如揚聲器和打印機等其它外圍輸出設(shè)備(未示出)。計算機1742通常使用到諸如打印服務(wù)器1788等一臺或多臺遠(yuǎn)程計算機的邏輯連接在聯(lián)網(wǎng)環(huán)境中操作,該打印服務(wù)器1788進(jìn)而被連接到一臺或數(shù)臺打印機。打印服務(wù)器1788可以是另一臺個人計算機、服務(wù)器、路由器、網(wǎng)絡(luò)PC、對等設(shè)備或其它普通網(wǎng)絡(luò)節(jié)點,并通常包括以上相對于計算機1742所描述的許多或全部元件。圖17中所示的邏輯連接包括局域網(wǎng)(LAN)1790和廣域網(wǎng)(WAN)1792。此類網(wǎng)絡(luò)環(huán)境常見于辦公室、企業(yè)范圍的計算機網(wǎng)絡(luò)、內(nèi)聯(lián)網(wǎng)以及因特網(wǎng)中。當(dāng)在LAN網(wǎng)絡(luò)環(huán)境中使用時,計算機1742通過網(wǎng)絡(luò)接口或適配器1794被連接到本地網(wǎng)絡(luò)。當(dāng)在WAN網(wǎng)絡(luò)環(huán)境中使用時,計算機1742通常包括調(diào)制解調(diào)器1796或其它用于通過廣域網(wǎng)1792(諸如因特網(wǎng))建立通信的裝置??蓛?nèi)置或外置的調(diào)制解調(diào)器1796經(jīng)由串行端口接口1768被連接到總線1748。在聯(lián)網(wǎng)環(huán)境中,相對于個人計算機1742所描述的程序模塊或其部分可被存儲在遠(yuǎn)程存儲器存儲設(shè)備中??梢哉J(rèn)識到,所示網(wǎng)絡(luò)連接是示例性的,并可使用其它用于在計算機之間建立通信鏈路的裝置。一般而言,計算機1742的數(shù)據(jù)處理器是通過在不同時間被存儲在計算機的各個計算機可讀存儲介質(zhì)中的指令來編程的。程序和操作系統(tǒng)通常被分布在例如軟盤或CD-ROM上。它們被從那里安裝或加載到計算機的次級存儲器中。在執(zhí)行時,它們至少被部分地加載到計算機的主電子存儲器中。當(dāng)這些及其它各種類型的計算機可讀存儲介質(zhì)包含用于結(jié)合微處理器或其它數(shù)據(jù)處理器實現(xiàn)所述的塊的指令時,本文中所描述的系統(tǒng)包括此類介質(zhì)。當(dāng)根據(jù)在此描述的方法和技術(shù)編程時,所述系統(tǒng)還可以包括計算機自身。出于說明目的,本文中將諸如操作系統(tǒng)等程序及其它可執(zhí)行程序組件示為離散的塊,盡管可意識到,此類程序和組件在各個時間駐留在計算機的不同存儲組件中,并由計算機的一個或多個數(shù)據(jù)處理器執(zhí)行。結(jié)論上述各個實施例提供一種能允許第三方組件編寫者能容易地將新的類插入到系統(tǒng)中的可插入體系結(jié)構(gòu)。提供了一種允許從多個數(shù)據(jù)提供程序檢索數(shù)據(jù)的路由系統(tǒng)。此外,一種名稱解析管道將人類提供的名稱解析為內(nèi)部的規(guī)范名稱。此外,各個實施例為客戶機提供了準(zhǔn)確地指定它想要從對象檢索的數(shù)據(jù)的能力。一種用于從對象檢索數(shù)據(jù)的極其高效的機制使用優(yōu)化的類型映射。一旦類型映射被構(gòu)建,就無需再執(zhí)行任何串比較或搜索。還提供了能夠支持任何數(shù)據(jù)的單個可插入接口。這意味著就建立而言,只需有一種類型的可安裝對象。其它對象類型可通過集合從工廠對象獲得。這可被用來構(gòu)建例如管道元素。此外,提供了一組允許系統(tǒng)中的任何對象能容易地支持查詢、支持通知——包括經(jīng)過濾的通知、支持高速緩存和工作調(diào)度的服務(wù)。所描述的實施例還通過訪問適配器提供隧穿任何協(xié)議的能力或可處理一組基本類型的傳輸。各個實施例還支持提供在下級協(xié)議上傳輸?shù)膶ο蠹?、以及允許下級(和上級)協(xié)議被動態(tài)添加到系統(tǒng)中的能力。此外,提供了一種異步數(shù)據(jù)接口。這是很重要的,因為每當(dāng)出現(xiàn)大量最終為IO綁定的數(shù)據(jù)寫時,同步接口會阻塞服務(wù)器。它還簡化了UI編程,因為單個UI線程可執(zhí)行,并且不會對其正在執(zhí)行的操作停頓。此外,批處理接口允許對象命令、獲取、設(shè)置、查詢和通知請求的任意分組。這是重要的,因為它使客戶機能夠支持諸如刪除打印機集合等操作。它還是有利的,因為它允許減少網(wǎng)絡(luò)延遲的作用。例如,當(dāng)UI想要檢索關(guān)于特定隊列的若干屬性時,它可將其所有請求批處理到一個消息,而這一個消息導(dǎo)致一次網(wǎng)絡(luò)往返,而不是在順序檢索數(shù)據(jù)的情況下所需要的多次網(wǎng)絡(luò)往返。此外,各個實施例可提供幾乎完全無狀態(tài)的接口,唯一的例外是通知。此外,通過利用客戶機對象集合簡化了該編程模型。一旦對象被成功的批處理執(zhí)行填充,即可保證對被檢索的數(shù)據(jù)的所有后續(xù)操作都將成功,因為它們被存儲在對象狀態(tài)中。該編程模型還巧妙地使通知和查詢客戶機語義幾乎完全相同。此外,CDI在后續(xù)迭代中或在某些集合中實現(xiàn)以下能力。首先,CDI實現(xiàn)通過標(biāo)準(zhǔn)類型元數(shù)據(jù)系統(tǒng)發(fā)現(xiàn)新數(shù)據(jù)類型的能力。它允許諸如通用調(diào)試接口和數(shù)據(jù)查詢接口等某些特征。第二,因為所有集合都具有同一接口,所以它們可在另一個進(jìn)程或應(yīng)用程序域中被沙箱化。第三,因為所有集合都具有同一接口,所以它允許系統(tǒng)使任何集合處于維護(hù)模式,并通過實現(xiàn)調(diào)用計數(shù)填充程序來卸載該集合。對升級現(xiàn)有組件的設(shè)置來說這是極其有用的。第四,通過允許批次也被事務(wù)化,事務(wù)式支持可被相當(dāng)容易地添加。最后,因為所有對象都使用同一接口,所以諸如裝飾器等模式可被容易地添加到系統(tǒng)中。這提供了使系統(tǒng)能由第三方以非常靈活的方式擴展的可能性。盡管是以結(jié)構(gòu)化特征和/或方法性步驟專屬的語言描述了本發(fā)明,但是應(yīng)當(dāng)理解,在所附權(quán)利要求書中定義的發(fā)明不必局限于所描述的具體特征或步驟。相反,這些具體特征和步驟是作為實現(xiàn)要求保護(hù)的發(fā)明的較佳形式公開的。權(quán)利要求1.一個或多個其上具有計算機可讀指令的計算機可讀介質(zhì),當(dāng)所述計算機指令被執(zhí)行時,提供一種軟件體系結(jié)構(gòu),所述軟件體系結(jié)構(gòu)被配置成提供被配置成提供通用數(shù)據(jù)模型的接口;提供異步客戶機調(diào)度,它允許客戶機或客戶機應(yīng)用程序開始數(shù)據(jù)請求,所述數(shù)據(jù)請求立即將控制返回給客戶機線程;以及提供異步服務(wù)器調(diào)度,其中服務(wù)器可異步地服務(wù)來自所述客戶機的請求。2.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供取消,在所述取消中所述服務(wù)器上正在進(jìn)行中的調(diào)用可由所述客戶機在任何時候取消。3.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送給所述服務(wù)器。4.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供事務(wù)式調(diào)用,在所述事務(wù)式調(diào)用中可向一批動作賦予它必須全部執(zhí)行或者不改變所述服務(wù)器的狀態(tài)的語義。5.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供并行調(diào)用,在所述并行調(diào)用中可向一批動作賦予所有項目可并行執(zhí)行的語義。6.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供截取,在所述截取中能執(zhí)行以下一個或多個動作的組件可被插入到所述體系結(jié)構(gòu)中監(jiān)視相關(guān)聯(lián)的系統(tǒng)、同步地響應(yīng)于所述系統(tǒng)、或者修改所述系統(tǒng)的行為。7.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供反射,通過所述反射,給定的一類對象所支持的屬性可被檢索。8.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送到所述服務(wù)器;以及事務(wù)式調(diào)用,在所述事務(wù)式調(diào)用中一批動作可被賦予它必須全部執(zhí)行或者不改變所述服務(wù)器的狀態(tài)的語義。9.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送到所述服務(wù)器;以及并行調(diào)用,在所述并行調(diào)用中可向一批動作賦予所有項目必須并行執(zhí)行的語義。10.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送到所述服務(wù)器;事務(wù)式調(diào)用,在所述事務(wù)式調(diào)用中可向一批動作賦予它必須全部執(zhí)行或者不改變所述服務(wù)器的狀態(tài)的語義;以及并行調(diào)用,在所述并行調(diào)用中可向一批動作賦予所有項目必須并行執(zhí)行的語義。11.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送到所述服務(wù)器;以及截取,在所述截取中能執(zhí)行以下一個或多個動作的組件可被插入到所述體系結(jié)構(gòu)中監(jiān)視相關(guān)聯(lián)的系統(tǒng)、同步地響應(yīng)于所述系統(tǒng)、或者修改所述系統(tǒng)的行為。12.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送到所述服務(wù)器;以及反射,通過所述反射,給定的一類對象所支持的屬性可被檢索。13.如權(quán)利要求1所述的一個或多個計算機可讀介質(zhì),其特征在于,所述軟件體系結(jié)構(gòu)被配置成提供批處理,在所述批處理中客戶機可構(gòu)建任意的一系列動作,并使所述動作作為一個單元被發(fā)送到所述服務(wù)器;反射,通過所述反射,給定的一類對象所支持的屬性可被檢索;以及截取,在所述截取中能執(zhí)行以下一個或多個動作的組件可被插入到所述體系結(jié)構(gòu)中監(jiān)視相關(guān)聯(lián)的系統(tǒng)、同步地響應(yīng)于所述系統(tǒng)、或者修改所述系統(tǒng)的行為。14.一個或多個其上具有計算機可讀指令的計算機可讀介質(zhì),當(dāng)所述計算機指令被執(zhí)行時,提供一種軟件體系結(jié)構(gòu),所述軟件體系結(jié)構(gòu)包括打印系統(tǒng),具有公共數(shù)據(jù)接口,它用作到批處理路由器的接口,所述公共數(shù)據(jù)接口被配置成允許來自客戶機的消息被構(gòu)建并被調(diào)度到所述批處理路由器,并將響應(yīng)發(fā)送到所述客戶機;批處理路由器,它與所述公共數(shù)據(jù)接口通信地鏈接,并被配置成接收由所述公共數(shù)據(jù)接口傳入的消息,并將所述消息異步地調(diào)度到一個或多個集合;插件表,它被配置成跟蹤消息處理插件,其中所述消息處理插件被配置成接收和處理預(yù)期目標(biāo)為一個或多個集合的消息;以及截取表,它被配置成用于截取和修改目標(biāo)為一個或多個對象的消息。15.如權(quán)利要求14所述的一個或多個計算機可讀介質(zhì),其特征在于,所述消息可包含目標(biāo)為一個或多個插件的一個或多個操作。16.如權(quán)利要求14所述的一個或多個計算機可讀介質(zhì),其特征在于,還包括一消息插件,它與所述批處理路由器通信地相關(guān)聯(lián),并被配置成從所述批處理路由器接收消息集并在適當(dāng)情況下將所述消息發(fā)送給另一個設(shè)備。17.如權(quán)利要求14所述的一個或多個計算機可讀介質(zhì),其特征在于,還包括一消息服務(wù),它與所述批處理路由器通信地相關(guān)聯(lián),并被配置成接收消息并將所述消息分解為集合接口上的一系列調(diào)用。18.如權(quán)利要求14所述的一個或多個計算機可讀介質(zhì),其特征在于,還包括一消息服務(wù),它與所述批處理路由器通信地相關(guān)聯(lián),并被配置成接收消息,并將所述消息分解為集合接口上的一系列調(diào)用,并且其中,所述消息服務(wù)被配置成執(zhí)行以下任務(wù)中的一個或多個將消息分配給線程;允許在多個延遲的調(diào)用中響應(yīng)消息;從集合中的對象檢索適當(dāng)?shù)臄?shù)據(jù)來填充消息;處理取消操作;將對象實例高速緩存;透明地鎖定對象;或者為在集合中維護(hù)的對象執(zhí)行反射服務(wù)。19.如權(quán)利要求14所述的一個或多個計算機可讀介質(zhì),其特征在于,還包括一個或多個對象集合,其中單個集合維護(hù)一組同類的對象。20.如權(quán)利要求14所述的一個或多個計算機可讀介質(zhì),其特征在于,還包括一個或多個對象集合,其中單個集合維護(hù)一組同類的對象,且其中單個集合被實現(xiàn)為從DLL檢索的COM接口。全文摘要本文描述了一種系統(tǒng)數(shù)據(jù)接口和相關(guān)的體系結(jié)構(gòu)。各個實施例可提供以下能力中的一個或多個通用數(shù)據(jù)模型、異步客戶機和服務(wù)器調(diào)度、取消、批處理、事務(wù)式調(diào)用、并行調(diào)用、截取、或者反射。在一個實施例中,該系統(tǒng)數(shù)據(jù)接口在打印系統(tǒng)的上下文中被使用。文檔編號G06F9/46GK1869923SQ20061000379公開日2006年11月29日申請日期2006年2月10日優(yōu)先權(quán)日2005年3月10日發(fā)明者A·F·馬克色,M·A·勞倫斯申請人:微軟公司
網(wǎng)友詢問留言 已有0條留言
  • 還沒有人留言評論。精彩留言會獲得點贊!
1