基于COM的三層應(yīng)用技術(shù)分析_第1頁(yè)
基于COM的三層應(yīng)用技術(shù)分析_第2頁(yè)
基于COM的三層應(yīng)用技術(shù)分析_第3頁(yè)
基于COM的三層應(yīng)用技術(shù)分析_第4頁(yè)
基于COM的三層應(yīng)用技術(shù)分析_第5頁(yè)
已閱讀5頁(yè),還剩15頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、基于COM+的三層應(yīng)用技術(shù)分析1. 系統(tǒng)功能11.1系統(tǒng)需求分析11.2小區(qū)物業(yè)系統(tǒng)的功能模塊12. 系統(tǒng)架構(gòu)22.1兩層框架22.2三層架構(gòu)22.3兩層和三層的優(yōu)缺點(diǎn)33. COM+的由來和演變34. 在delphi中開發(fā)COM+組件54.1建立工程54.2編寫接口函數(shù)64.3注冊(cè)和安裝64.4設(shè)置調(diào)試65. COM+技術(shù)分析75.1概念分析75.2 COM+實(shí)現(xiàn)代碼分析:85.2.1 GUID8記錄類型8接口95.2.4 接口實(shí)現(xiàn)類105.2.5 COM+對(duì)象生成156. COM+的優(yōu)缺點(diǎn)186.1COM+的優(yōu)點(diǎn)186.2COM+的缺點(diǎn)181. 系統(tǒng)功能1.1系統(tǒng)需求分析一個(gè)小區(qū)的物業(yè),負(fù)

2、責(zé)整個(gè)小區(qū)的管理。包含的內(nèi)容有很多,包括對(duì)小區(qū)內(nèi)所有的公共設(shè)備和建筑進(jìn)行管理、維修;對(duì)小區(qū)內(nèi)所有的單元戶進(jìn)行信息統(tǒng)計(jì);對(duì)小區(qū)內(nèi)的入住人員進(jìn)行管理;負(fù)責(zé)小區(qū)內(nèi)的綠化和清潔;查收水電費(fèi)和物業(yè)費(fèi);對(duì)小區(qū)內(nèi)車輛進(jìn)行統(tǒng)計(jì),并收取停車費(fèi);提供投訴平臺(tái),并進(jìn)行處理;對(duì)小區(qū)內(nèi)工作人員進(jìn)行統(tǒng)計(jì);對(duì)外來車輛的管理;對(duì)小區(qū)內(nèi)工作人員的工資、休假等管理;設(shè)置小區(qū)的單位物業(yè)費(fèi)用。1.2小區(qū)物業(yè)系統(tǒng)的功能模塊為了在短期內(nèi)實(shí)現(xiàn)系統(tǒng),體現(xiàn)開發(fā)和使用COM+組件以及三層架構(gòu)的精髓,將小區(qū)物業(yè)的管理流程進(jìn)行簡(jiǎn)化。系統(tǒng)要實(shí)現(xiàn)的模塊如圖1.1所示。圖1.1系統(tǒng)功能模塊單元樓模塊實(shí)現(xiàn):錄入小區(qū)內(nèi)的樓棟信息,包括樓棟名稱、高度、一層的房

3、間數(shù)、占地面積等。修改小區(qū)內(nèi)的樓棟信息。單元戶模塊實(shí)現(xiàn):錄入小區(qū)內(nèi)的單元戶信息,包括所在樓棟、所在高度、房間號(hào)、占地面積、名稱等。修改單元戶的信息,查找單元戶信息等。業(yè)主模塊實(shí)現(xiàn):錄入入住人員的基本信息,包括姓名、性別、所在單元戶、入住時(shí)間、聯(lián)系電話和身份證號(hào)碼。修改業(yè)主信息、刪除業(yè)主信息,查找業(yè)主信息等。投訴模塊實(shí)現(xiàn):錄入投訴信息、刪除投訴信息、修改投訴信息等。包括投訴時(shí)間、投訴人、投訴內(nèi)容。報(bào)修維修模塊實(shí)現(xiàn):錄入報(bào)修記錄,包括報(bào)修時(shí)間、報(bào)修內(nèi)容。并可修改報(bào)修記錄。錄入微機(jī)記錄,包括維修時(shí)間、維修費(fèi)用,可修改維修記錄。系統(tǒng)用戶模塊實(shí)現(xiàn):添加一個(gè)系統(tǒng)用戶,包括用戶名、登錄名、登錄密碼??蓜h除和

4、修改選定記錄。停車位和車輛模塊實(shí)現(xiàn):錄入一個(gè)車位信息,包括所屬樓和車位編號(hào)。錄入車輛和車主信息,并對(duì)車輛和車主信息進(jìn)行修改、刪除、查詢操作。添加一個(gè)車位的繳費(fèi)信息??刹榭茨骋粋€(gè)車位的歷史繳費(fèi)記錄等。水電費(fèi)和物業(yè)費(fèi)模塊實(shí)現(xiàn):每一個(gè)月,錄入所有單元戶的用電量、用水量、應(yīng)繳電費(fèi)、應(yīng)繳水費(fèi)、應(yīng)繳物業(yè)費(fèi)。并可對(duì)錄入信息進(jìn)行修改、查詢。錄入每個(gè)單元戶的實(shí)際繳費(fèi)記錄,并可修改、查詢。2. 系統(tǒng)架構(gòu)2.1兩層框架 在數(shù)據(jù)庫(kù)開發(fā)中,兩層框架就是C/S模式??蛻魴C(jī)試應(yīng)用程序,而服務(wù)器是數(shù)據(jù)庫(kù)服務(wù)器。數(shù)據(jù)庫(kù)用來存儲(chǔ)系統(tǒng)中的數(shù)據(jù),而應(yīng)用程序則負(fù)責(zé)連接數(shù)據(jù)庫(kù),并擔(dān)當(dāng)了顯示數(shù)據(jù),處理用戶輸入數(shù)據(jù),更新、保存保存數(shù)據(jù)到數(shù)據(jù)

5、庫(kù)的任務(wù)。也就是說,客戶機(jī)承擔(dān)了數(shù)據(jù)顯示和業(yè)務(wù)流程的所有任務(wù)。而數(shù)據(jù)顯示和整個(gè)系統(tǒng)的業(yè)務(wù)也是融合在一起,沒有明顯的分界線的。2.2三層架構(gòu) 三層架構(gòu)與兩層C/S相比,多了一個(gè)中間件。中間件也叫做應(yīng)用程序服務(wù)器,中間件負(fù)責(zé)連接數(shù)據(jù)庫(kù),更新并保存數(shù)據(jù)到數(shù)據(jù)庫(kù),響應(yīng)客戶端的請(qǐng)求并返回?cái)?shù)據(jù)等??蛻舳藨?yīng)用程序不再直接與數(shù)據(jù)庫(kù)連接,而是通過中間件關(guān)聯(lián),并且所有的業(yè)務(wù)流程和數(shù)據(jù)處理都放置到中間件中。客戶端只用來顯示數(shù)據(jù),與用戶進(jìn)行交互。2.3兩層和三層的優(yōu)缺點(diǎn)因?yàn)閮蓪蛹軜?gòu)的所有操作都集中到客戶端,導(dǎo)致兩層架構(gòu)的客戶端比較龐大,并且更新系統(tǒng)要對(duì)所有的客戶端進(jìn)行更新,不僅難于維護(hù),維護(hù)成本也較高。當(dāng)系統(tǒng)模塊中出

6、現(xiàn)重復(fù)的業(yè)務(wù)邏輯也要進(jìn)行多次編程,代碼復(fù)用率較低。但是采用兩層架構(gòu)有利于團(tuán)隊(duì)間進(jìn)行模塊化得開發(fā),只要每個(gè)人負(fù)責(zé)一個(gè)或者多個(gè)模塊的數(shù)據(jù)顯示和業(yè)務(wù)處理。因?yàn)槿龑蛹軜?gòu)將數(shù)據(jù)顯示和業(yè)務(wù)邏輯分離,使得客戶端比較小,實(shí)現(xiàn)了瘦客戶機(jī)的結(jié)構(gòu)。當(dāng)每次更新和升級(jí)業(yè)務(wù)處理的時(shí)候,都可以只升級(jí)服務(wù)器端,降低了維護(hù)的成本和難度。此外,三層架構(gòu)將所有的業(yè)務(wù)邏輯進(jìn)行集中管理,提高了代碼的利用率(相同的業(yè)務(wù)流程,只需要進(jìn)行一次編程,在不同的模塊中進(jìn)行調(diào)用即可)。但是,與兩層架構(gòu)相比,三層架構(gòu)的系統(tǒng)也由它的不足之處。三層架構(gòu)的中間層可以是以dll動(dòng)態(tài)鏈接庫(kù)或者EXE可執(zhí)行程序的形式存在,但不管是哪一種方式,都導(dǎo)致三層框架的系統(tǒng)

7、在編碼和調(diào)試的時(shí)候,更容易出錯(cuò)。三層框架系統(tǒng)的速度和效率也低于兩層架構(gòu)的系統(tǒng)。并且業(yè)務(wù)邏輯和顯示層也不容易分割,容易出現(xiàn)設(shè)計(jì)問題。Delphi的三層框架技術(shù),也由一定難度,入門到完全掌握需要比較長(zhǎng)得時(shí)間。3. COM+的由來和演變COM(component object model,組件對(duì)象模型)是客戶端和COM對(duì)象之間進(jìn)行交流的一種二進(jìn)制規(guī)范。這個(gè)規(guī)范允許用合適的語(yǔ)言把一些代碼編程一個(gè)組件,并且允許在編程語(yǔ)言中使用這個(gè)組件或功能,即使語(yǔ)言不通,也不會(huì)有問題,所以說COM是跨語(yǔ)言的,并且與編程語(yǔ)言無關(guān)。COM要實(shí)現(xiàn)的就是客戶和正在使用的COM對(duì)象的透明定位。而所謂的合適的語(yǔ)言是指:COM的跨語(yǔ)

8、言特性是狹隘的。理論上,COM生成的dll動(dòng)態(tài)鏈接庫(kù)或者EXE可執(zhí)行程序可以被任何語(yǔ)言所使用,但是一些非面向?qū)ο蟮木幊陶Z(yǔ)言,比如VB,就不能用來創(chuàng)建和使用COM對(duì)象。COM除了是一個(gè)二進(jìn)制規(guī)范外,還是一種實(shí)現(xiàn)。它以一個(gè)COM庫(kù)和一組API函數(shù)的形式,提供了創(chuàng)建和管理COM對(duì)象的途徑。同時(shí),它還可以說是一個(gè)服務(wù),它為其他的應(yīng)用程序提供了COM組件實(shí)現(xiàn)的接口函數(shù)。無論COM是以進(jìn)程內(nèi)(In-Process,dll動(dòng)態(tài)鏈接庫(kù)的形式)COM還是以進(jìn)程外(Out-Process,可執(zhí)行程序的形式)COM的形式,都只能為本機(jī)內(nèi)的應(yīng)用程序提供服務(wù),使用COM組件內(nèi)的接口函數(shù)。為了解決COM在分布式上的缺陷,

9、使COM能夠在不同的計(jì)算機(jī)之間進(jìn)行通信,Microsoft又研發(fā)了DCOM。DCOM(分布式COM)是對(duì)COM的進(jìn)一步的擴(kuò)展,一種無縫的擴(kuò)充技術(shù)。DCOM使COM能夠支持在局域網(wǎng)、廣域網(wǎng)甚至Internet上不同計(jì)算機(jī)的對(duì)象之間的通訊。DCOM的跨計(jì)算機(jī)的特性,是因?yàn)镈COM封裝了網(wǎng)絡(luò)通訊的底層細(xì)節(jié),使開發(fā)者致力于應(yīng)用程序的業(yè)務(wù)邏輯開發(fā)。MTS(Microsoft Transaction Server,事務(wù)處理服務(wù)),它是Windows NT操作系統(tǒng)推出的一個(gè)中間件產(chǎn)品。Microsoft提出這個(gè)服務(wù),是為了支出開發(fā)企業(yè)應(yīng)用程序中多線程和分布式事務(wù)等復(fù)雜事務(wù)的處理,讓windows程序員開發(fā)以

10、組件為向?qū)У姆植际綉?yīng)用系統(tǒng)。MTS具備在同質(zhì)和異質(zhì)數(shù)據(jù)庫(kù)之間的數(shù)據(jù)進(jìn)行Two phase commit的功能,允許大量的客戶端應(yīng)用程序同時(shí)執(zhí)行,并提供了數(shù)據(jù)庫(kù)事務(wù)的管理工作。將MTS和DCOM結(jié)合起來,很容易的就能開發(fā)出一個(gè)支持事務(wù)處理和多線程、并且保證能夠運(yùn)行在同一臺(tái)或者不同的機(jī)器上的中間件作為一個(gè)系統(tǒng)的應(yīng)用服務(wù)器。出現(xiàn)DCOM和MTS之后,開發(fā)分布式的系統(tǒng)的基本框架就可以采用如圖3.1所示的多層框架。圖3.1COM/MTS多層框架雖然MTS的出現(xiàn),為COM提供了事務(wù)處理,安全控制,資源分發(fā)控制等服務(wù),為COM開發(fā)提供了一個(gè)比較完整的系統(tǒng)結(jié)構(gòu)。但是,因?yàn)闅v史的原因,DCOM和MTS的優(yōu)勢(shì)還不

11、為windows程序員所認(rèn)識(shí),DCOM和MTS也不能很好的進(jìn)行融合。于是,在Windows 2000中,微軟引進(jìn)了COM+的概念。COM+不是對(duì)COM的簡(jiǎn)單升級(jí),它幾乎包含了COM所有的功能,并且融合了DCOM和MTS的核心技術(shù)。也就說說,COM+不僅可以提供了客戶程序和COM+組件之間的透明定位,無論這個(gè)客戶程序和COM+組件是不是在一個(gè)計(jì)算機(jī)中,同時(shí),COM+也提供了對(duì)事務(wù)的處理、事件機(jī)制、目錄和基于角色的安全機(jī)制等系統(tǒng)服務(wù)。COM+的出現(xiàn)使得開發(fā)一個(gè)三層框架的系統(tǒng)更加清晰和簡(jiǎn)單。如圖3.2COM+三層框架。圖3.2 COM+三層架構(gòu)4. 在delphi中開發(fā)COM+組件4.1建立工程在d

12、elphi的集成開發(fā)環(huán)境中,提供了創(chuàng)建COM+組件的模板。按照如下的七個(gè)步驟就能創(chuàng)建一個(gè)COM+組件的框架。1、 打開delphi集成開發(fā)工具2、 選擇File菜單下的Newother選項(xiàng)3、 在對(duì)話框中,選擇ActiveX頁(yè)面4、 選擇Transactional Object類型的工程,進(jìn)行創(chuàng)建5、 在彈出的對(duì)話框中,輸入Coclass Name。6、 選擇線程模式為Aparment(默認(rèn))7、 選擇事務(wù)支持模式為Supports transactional。4.2編寫接口函數(shù)創(chuàng)建工程后,Delphi集成開發(fā)工具會(huì)自動(dòng)創(chuàng)建三個(gè)文件。一個(gè)工程文件,一個(gè)類型庫(kù)文件,一個(gè)COM+接口實(shí)現(xiàn)類文件。在

13、delphi中編寫COM+組件十分容易,只要打開類型庫(kù)編輯器,在類型庫(kù)編輯器中,添加接口、接口函數(shù)、枚舉類型的變量或者記錄類型。在類型庫(kù)編輯器中所做的操作,都會(huì)直接反應(yīng)到類型庫(kù)文件中。并且添加的接口函數(shù)的實(shí)現(xiàn)代碼也會(huì)添加到實(shí)現(xiàn)類文件中。程序員要做的,就是填充實(shí)現(xiàn)類中不完整(實(shí)際上時(shí)沒有一行代碼的空函數(shù))的函數(shù)實(shí)現(xiàn)代碼,來完成系統(tǒng)的業(yè)務(wù)流程。4.3注冊(cè)和安裝編寫完COM+組件要實(shí)現(xiàn)的接口和服務(wù)之后,要為其他的應(yīng)用程序提供服務(wù)還需要將COM+組件注冊(cè)到操作系統(tǒng)中。如果用delphi集成開發(fā)環(huán)境進(jìn)行開發(fā),可以選擇RUN菜單下的Register ActiveX Server選項(xiàng),將COM+組件注冊(cè)到注

14、冊(cè)表中。此外,還可以運(yùn)行windows提供的一個(gè)程序Regsvr32.exe 來注冊(cè)組件。接著將COM+組件安裝到操作系統(tǒng)的COM+應(yīng)用程序中。選擇RUN菜單下的Install COM+ Objects選項(xiàng)。在對(duì)話框中選擇一個(gè)COM+應(yīng)用程序,或者創(chuàng)建一個(gè)新的COM+應(yīng)用程序。Delphi開發(fā)環(huán)境會(huì)自動(dòng)將COM+組件添加到COM+應(yīng)用程序中。之后,就能夠在組件服務(wù)中,找到我們開發(fā)的這個(gè)COM+組件。安裝COM+組件還有另外的一種方式就是,打開控制面板,進(jìn)入管理工具。選擇組件服務(wù),并打開COM+應(yīng)用程序列表。右鍵通過向?qū)Ы⒁粋€(gè)新的COM+應(yīng)用程序,并將建立的COM+組件添加到COM+應(yīng)用程序中

15、去。4.4設(shè)置調(diào)試在客戶端應(yīng)用程序調(diào)用COM+組件接口函數(shù)的時(shí)候,為方便調(diào)試,需要對(duì)COM+應(yīng)用程序和工程進(jìn)行設(shè)置。因?yàn)槟J(rèn)情況下,COM+是被自動(dòng)調(diào)用和啟動(dòng)的。設(shè)置過程如下:1、 在組件服務(wù)的COM+組件中,找到新添加的COM+組件應(yīng)用程序。2、 設(shè)置該COM+應(yīng)用程序的屬性高級(jí)頁(yè)面,選中在調(diào)試器中打開,并設(shè)置正確的調(diào)試路徑。3、 設(shè)置COM+工程。在Project菜單下,選中Options選項(xiàng)。4、 選中對(duì)話框的Link頁(yè)面。5、 選中EXE and DLL options下的兩個(gè)選項(xiàng)(include TD32 debug info和include remote debug symbols

16、)。6、 選中Run菜單下的Parameters選項(xiàng)。7、 選中對(duì)話框的Local頁(yè)面。8、 填寫Host Application為默認(rèn)值,填寫Parameters為COM+應(yīng)用程序的GUID值。這樣就能進(jìn)行調(diào)試了。5. COM+技術(shù)分析5.1概念分析前面出現(xiàn)的概念有:接口、COM+組件,COM+應(yīng)用程序。這三者之間的聯(lián)系如圖5.1所示:圖5.1接口、組件和COM+應(yīng)用程序也就是說一個(gè)COM+組件是由接口構(gòu)成的,它可以包含多個(gè)接口。而一個(gè)COM+應(yīng)用程序可以封裝多個(gè)COM+組件。5.2 COM+實(shí)現(xiàn)代碼分析:前面一章節(jié)中講到在創(chuàng)建工程之后,就生成了一個(gè)類型庫(kù)文件,該文件以*_TLB命名。*為工

17、程文件的名稱,同時(shí)也會(huì)生成一個(gè)實(shí)現(xiàn)接口的類文件稱之為實(shí)現(xiàn)類文件。在類型庫(kù)文件中,定義了三個(gè)GUID和接口以及自定義的函數(shù)和記錄類型。而在實(shí)現(xiàn)類文件則包含了在類型庫(kù)文件中定義的所有接口函數(shù)的實(shí)現(xiàn)代碼。 GUIDGUID(Globally Unique Identifier,全球唯一標(biāo)識(shí)符),是一個(gè)唯一性的標(biāo)識(shí)符。在類型庫(kù)文件的一開始,就定義了三個(gè)GUID類型的常數(shù)。1、 LIBID_Server:代表了唯一的類型庫(kù),它是COM+對(duì)象實(shí)現(xiàn)的類型庫(kù)的ID2、 IID_Iuptown代表了唯一的接口,是COM+對(duì)象的一個(gè)接口的ID3、 CLASS_uptown用于將COM+組件注冊(cè)到注冊(cè)表或者解除注冊(cè)

18、的時(shí)候起著關(guān)鍵性的作用,是生成COM+對(duì)象的重要標(biāo)識(shí)符。記錄類型在類型庫(kù)編輯器中添加一個(gè)記錄類型,delphi集成開發(fā)環(huán)境就會(huì)在類型庫(kù)文件中自動(dòng)添加對(duì)記錄類型的定義。舉例說明,在類型庫(kù)編輯器中添加一個(gè)記錄類型的變量并命名為Build,為這個(gè)記錄添加多個(gè)字段并設(shè)置每個(gè)字段的類型。點(diǎn)擊刷新按鈕后,在類型庫(kù)文件中,就能看到剛剛添加的記錄類型的定義。Build = packed record b_ID: Int64; b_name: WideString; b_address: WideString; b_high: Int64; b_home: Int64; b_size: Double; b_li

19、ft: WideString;end;首先,這個(gè)記錄類型與我們?cè)赿elphi中自己定義的記錄類型的區(qū)別是,多了一個(gè)packed的關(guān)鍵字。在delphi中,為了加快取記錄類型變量各個(gè)字段的速度,進(jìn)行了這樣的優(yōu)化:變量都是字節(jié)對(duì)齊的方式。所以會(huì)出現(xiàn)sizeof操作出來的結(jié)果和記錄類型的變量大小不一樣的情況。而packed關(guān)鍵字要求對(duì)記錄類型進(jìn)行壓縮,也就是說避免了delphi對(duì)記錄類型的優(yōu)化。這么做不進(jìn)節(jié)省了空間,更重要的是保證了不同的程序進(jìn)行通信的時(shí)候不出錯(cuò)。正是因?yàn)镃OM+組件允許不同的進(jìn)程調(diào)用它提供的服務(wù)(接口函數(shù)),該記錄除了使用packed進(jìn)行壓縮外,每個(gè)變量的類型也與一般的delphi

20、應(yīng)用程序有區(qū)別。比如用WideString代替String或者shortstring類型,用Int64代替Interget類型。事實(shí)上,在編寫COM+組件的時(shí)候,不管是函數(shù)或者過程的參數(shù)還是記錄類型的變量等,所有的對(duì)外變量都采用特殊的參數(shù)類型。這么做的好處是使得與其他進(jìn)程進(jìn)行通信的時(shí)候,互相兼容。接口COM+組件的基礎(chǔ)就是接口。編寫COM+組件最重要也是編寫COM+組件中的接口和接口中的函數(shù)。那么什么是接口呢?接口類似于delphi中的抽象類。因此不能定義一個(gè)接口的實(shí)例。但與抽象類的區(qū)別是,接口僅僅包含了一組實(shí)現(xiàn)不同功能的函數(shù)和過程,卻不能定義變量。也不能對(duì)接口中的函數(shù)限定范圍。所有的函數(shù)和過

21、程都默認(rèn)是public的,不存在private或者protect等修飾。并且接口是用關(guān)鍵字interface定義的,而不是用class。下面就是一個(gè)接口的定義:Iuptown = interface(IDispatch) 'CE8179DC-5579-4C47-BBFF-0CA70D28541E' function ConnectToDB: WideString; safecall; function ExecSQL(const sqlString: WideString): OleVariant; safecall; function DisConnect: WideStri

22、ng; safecall; function InsertToBuild(BuildbRecord: Build; out outString: WideString): Int64; safecall; function InsertToHome(HomeRecord: Home; out outString: WideString): Int64; safecall; function InsertToPeople(PeopleRecord: People; inHomeDate: TDateTime; out outString: WideString): Int64; safecall

23、; function SetParameter(const p_name: WideString; const p_value: WideString; var outString: WideString): Int64; safecall; function InsertToCar(CarRecord: Car; out outString: WideString): Int64; safecall; function UpdateCarUse(CarRecord: Car; out outString: WideString): Int64; safecall; ··&

24、#183;···從接口函數(shù)的聲明中可以看到,每個(gè)函數(shù)都有safecall標(biāo)注。原因是:普通函數(shù)都是采用register寄存器調(diào)用方式,delphi為register調(diào)用方式的函數(shù)的參數(shù)提供最多三個(gè)寄存器,用來提高函數(shù)調(diào)用的速度,超過三個(gè)的參數(shù)則采用堆棧方式。并且register調(diào)用采用從左到右的順序?qū)?shù)進(jìn)行賦值。而COM接口默認(rèn)的方法調(diào)用時(shí)stdcall標(biāo)準(zhǔn)調(diào)用,即使全部參數(shù)采用堆棧方式的調(diào)用形式來保持COM的跨語(yǔ)言兼容性。而COM+組件中的接口,是雙重接口。在類型庫(kù)編輯器中,定義一個(gè)函數(shù)的時(shí)候,所有的函數(shù)返回值都默認(rèn)為HResult。這是自動(dòng)化對(duì)象中所有函數(shù)都

25、要符合的一個(gè)規(guī)則。要?jiǎng)?chuàng)建一個(gè)想要有返回值的函數(shù),就將參數(shù)定義為out類型,或者將最后一個(gè)參數(shù)的返回值設(shè)定為函數(shù)名稱,類型為out+Refval類型。采用這種方式定義的函數(shù)可以捕捉異常,即使是方法中未被處理的異常,也可以被外套處理并通過HReuslt返回給調(diào)用者。在定義COM+組件的時(shí)候,要捕捉函數(shù)調(diào)用的異常,必須使用函數(shù)OLECheck進(jìn)行檢查。另外,windows中,標(biāo)準(zhǔn)的調(diào)用順序都是從右到左的。 接口實(shí)現(xiàn)類接口只有虛函數(shù),并且不能創(chuàng)建變量。要實(shí)現(xiàn)接口的函數(shù),就是生成一個(gè)接口的實(shí)現(xiàn)類。這個(gè)實(shí)現(xiàn)類繼承了一個(gè)對(duì)象類(Tobject的派生類),并包含一個(gè)或者多個(gè)接口。小區(qū)物業(yè)管理系統(tǒng)的實(shí)現(xiàn)類定義如

26、下:Tuptown = class(TMtsAutoObject, Iuptown) private con: TADOConnection; function ConnectToDB: WideString; safecall; function DisConnect: WideString; safecall; protected function ExecSQL(const sqlString: WideString): OleVariant; safecall; function InsertToBuild(BuildbRecord: Build; out outString: Wid

27、eString): Int64; safecall; function InsertToHome(HomeRecord: Home; out outString: WideString): Int64; safecall; function InsertToPeople(PeopleRecord: People; inHomeDate: TDateTime; out outString: WideString): Int64; safecall;······ public procedure initialize; override;

28、destructor Destroy; override;從delphi的集成開發(fā)環(huán)境中,可以看到小區(qū)物業(yè)管理系統(tǒng)中COM+組件的接口實(shí)現(xiàn)類Tuptown的繼承關(guān)系如圖5.2所示:圖5.2實(shí)現(xiàn)類的繼承關(guān)系 父類的含義1、TComObjectTComObject實(shí)現(xiàn)了IUnknown、ISupportErrorInfo、標(biāo)準(zhǔn)的COM聚集支持和一個(gè)對(duì)應(yīng)的類工廠支持。如果我們想創(chuàng)建一個(gè)輕量級(jí)的可連接客戶端的基于IUnknown接口的COM對(duì)象的話,COM對(duì)象就應(yīng)該從TComObject 類繼承。 2、TComObjectFactoryTComObjectFactory 是同TComObject對(duì)象配

29、合工作的。它把對(duì)應(yīng)的TComObject 公開為CoClass。TComObjectFactory 提供了CoClass的注冊(cè)功能(根據(jù)CLSIDs、線程模式、應(yīng)用程序ID等)。還實(shí)現(xiàn)了IClassFactory 和 IClassFactory2 接口以及標(biāo)準(zhǔn)的COM 對(duì)象許可證支持。簡(jiǎn)單地說如果要想創(chuàng)建TComObject對(duì)象,就會(huì)同時(shí)需要TComObjectFactory對(duì)象。3、TTypedComObjectTTypedComObject等于TComObject 和對(duì)IProvideClassInfo接口的支持。IProvideClassInfo 是自動(dòng)化的標(biāo)準(zhǔn)接口用來公開一個(gè)對(duì)象的類型

30、信息的(比如可獲得的名字、方法、支持的接口等,類型信息儲(chǔ)存在相關(guān)的類型庫(kù)中)。TTypedComObject 可以用來支持那些在運(yùn)行時(shí)能夠?yàn)g覽類型信息的客戶端,比如Visual Basic的TypeName 函數(shù)期望一個(gè)對(duì)象能夠?qū)崿F(xiàn)IProvideClassInfo 接口,以便通過類型信息確定對(duì)象的文檔名稱(documented name)。4、TTypedComObjectFactoryTTypedComObjectFactory 是和TTypedComObject配合工作的。就等于TComObjectFactory + 提供緩存了的TTypedComObject類型信息(ITypeInfo

31、)引用。一句話,創(chuàng)建TTypedComObject必然會(huì)同時(shí)創(chuàng)建TypedComObjectFactory 類工廠。5、TAutoObjectTAutoObject 等于TTypedComObject+實(shí)現(xiàn)IDispatch接口。TAutoObject適用于實(shí)現(xiàn)支持自動(dòng)化控制的COM對(duì)象。6、TAutoObjectFactoryTAutoObjectFactory顯然是同TAutoObject密不可分的。它等于TTypedComObjectFactory +提供了TAutoObject的接口和連接點(diǎn)事件接口的緩存類型信息 (ITypeInfo)。7、TMtsAutoObjectDelphi幫助

32、文檔中,是這么描述TMtsAutoObject類的:TMtsAutoObject是MTS應(yīng)用程序服務(wù)器的MTS對(duì)象和接口的裝載器。而MTS自動(dòng)化對(duì)象是那些完成了IObjectControl接口的雙重接口自動(dòng)化服務(wù)器。MTS自動(dòng)化對(duì)象將MTS的事物處理、安全機(jī)制等特性和自動(dòng)化對(duì)象的特征融合在一起。從這段話中,可以看出,所有的MTS對(duì)象都是要完成IObjectControl接口的。 IUnknown接口從圖中可以看出,所有的接口的祖先都是IUnknown接口。IUnknown是定義在system.pas文件中的一個(gè)接口。它的定義如下:type IInterface = interface '

33、;00000000-0000-0000-C000-000000000046' function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; IUnknown = IInterface;可以看到,IUnknown接口包含了三個(gè)函數(shù)。因?yàn)榻涌谒械暮瘮?shù)都是公共的虛函數(shù),所以這三個(gè)函數(shù)都是由IUnknown的派生類來實(shí)現(xiàn)的。1、 QueryInterface函數(shù)

34、:返回某個(gè)COM對(duì)象中的接口指針的函數(shù)。從圖上可以看出,一個(gè)類可以繼承一個(gè)父類和多個(gè)接口,并且一個(gè)COM對(duì)象可以聚合多個(gè)內(nèi)部接口。如果在應(yīng)用程序中,使用COM對(duì)象沒有定義或者包含的接口,就會(huì)提示接口不存在等錯(cuò)誤信息。因此使用一個(gè)接口前可以使用QueryInterface函數(shù)判斷某一個(gè)COM對(duì)象是否包含了將要使用到的接口。調(diào)用該函數(shù)的時(shí)候,輸入?yún)?shù)是某個(gè)接口的ID(IID),當(dāng)該COM對(duì)象實(shí)現(xiàn)了要查找的接口的時(shí)候,就返回?cái)?shù)值S_OK(數(shù)值0),而如果沒有找到該接口,則返回?cái)?shù)值E_NOINTERFACE (數(shù)值HRESULT($80004002))。2、 _AddRef函數(shù):接口是引用計(jì)數(shù)的。當(dāng)客

35、戶端從COM對(duì)象中獲得一個(gè)接口時(shí),該函數(shù)就增加了一個(gè)接口的引用計(jì)數(shù)。3、 _Release函數(shù):而當(dāng)客戶端釋放了接口調(diào)用時(shí),該函數(shù)釋放掉一個(gè)了接口的引用計(jì)數(shù)。這三個(gè)函數(shù)的實(shí)現(xiàn),定義在類TComObject中。詳細(xì)如下:TComObject = class(TObject, IUnknown, ISupportErrorInfo) Private······FRefCount: Integer;······ protected IUnknown function IUnknow

36、n.QueryInterface = ObjQueryInterface; function IUnknown._AddRef = ObjAddRef; function IUnknown._Release = ObjRelease; IUnknown methods for other interfaces function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall;function _Release: Integer; stdcall;

37、83;·····Publicfunction ObjAddRef: Integer; virtual; stdcall;function ObjQueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;function ObjRelease: Integer; virtual; stdcall;······需要提到的是,因?yàn)榫酆系脑?,使得一個(gè)IUnknown的派生類中,可能包含了同名的接口函數(shù)。如果這些接

38、口函數(shù)的實(shí)現(xiàn)是相同的,就定義一個(gè)共同的方法。但如果是不同的實(shí)現(xiàn)函數(shù),就需要使用到方法分辨子句。在TComObject類的定義中,function IUnknown.QueryInterface = ObjQueryInterface; function IUnknown._AddRef = ObjAddRef; function IUnknown._Release = ObjRelease;這三條語(yǔ)句就是方法分辨語(yǔ)句。當(dāng)調(diào)用IUnknown的三個(gè)函數(shù)的時(shí)候,實(shí)際上是在執(zhí)行ObjAddRef、ObjRelease、ObjQueryInterface這三個(gè)函數(shù)。ObjAddRef和ObjRelea

39、se函數(shù)共同維護(hù)了接口的引用計(jì)數(shù)變量FRefCount,承擔(dān)了COM+組件的生存期。這兩個(gè)函數(shù)和變量FRefCount只在控制COM+組件的生存期的時(shí)候才有用,其他時(shí)候完全沒有意義。在delphi編程中,可以不用考慮這兩個(gè)函數(shù)的調(diào)用,系統(tǒng)會(huì)自動(dòng)管理FRefCount變量。但是一旦脫離了delphi,就需要程序員自己調(diào)用_AddRef 和_Release函數(shù)來管理COM+組件的生存期。 創(chuàng)建接口的函數(shù)在創(chuàng)建工程的一開始,就輸入了一個(gè)CoClass name。這個(gè)名字,在*_TLB文件末尾出現(xiàn)。Couptown = class class function Create: Iuptown; cla

40、ss function CreateRemote(const MachineName: string): Iuptown; end;用delphi集成開發(fā)環(huán)境創(chuàng)建的每一個(gè)COM+接口,都會(huì)有一個(gè)對(duì)應(yīng)的CoClass與之對(duì)應(yīng)。這個(gè)CoClass是系統(tǒng)自動(dòng)生成的,用來創(chuàng)建接口的函數(shù)。它提供了兩個(gè)函數(shù),一個(gè)用來創(chuàng)建本地COM+組件接口,另一個(gè)用來創(chuàng)建遠(yuǎn)程的COM+組件接口。這兩個(gè)函數(shù)調(diào)用了操作系統(tǒng)中的動(dòng)態(tài)鏈接庫(kù)函數(shù),并使用olecheck函數(shù)來判斷是否接口創(chuàng)建成功。詳細(xì)的內(nèi)容將在COM+是如何啟動(dòng)的那一章節(jié)中講述?,F(xiàn)在需要知道的是,CoClass的兩個(gè)函數(shù),在COM+對(duì)象的創(chuàng)建中,起了關(guān)鍵的作用。

41、COM+對(duì)象生成用來創(chuàng)建COM+對(duì)象的接口的函數(shù),已經(jīng)清楚了。那么接口實(shí)現(xiàn)類是如何創(chuàng)建并和接口聯(lián)系在一起的呢?COM+對(duì)象的創(chuàng)建和初始化,都在接口實(shí)現(xiàn)類文件最后的initialization部分。initialization部分是delphi用于初始化的特殊部分。當(dāng)程序啟動(dòng)后,會(huì)先行調(diào)用這部分的代碼進(jìn)行初始化。小區(qū)物業(yè)管理系統(tǒng)服務(wù)器的初始化代碼如下:initialization TAutoObjectFactory.Create(ComServer, Tuptown, Class_uptown,ciMultiInstance, tmApartment); ComServer:TComServe

42、r。ComServer是定義在ComServ單元的全局變量。該變量是用來注冊(cè)和撤銷注冊(cè)COM+服務(wù)的對(duì)象。 Tuptown是程序員自己創(chuàng)建的接口實(shí)現(xiàn)類。 Class_uptown是GUID類型的常量。將COM+注冊(cè)到注冊(cè)表的HKEY_CLASSES_ROOT/CLSID目錄下,就要用到Class_uptown常量值。 ciMultiInstance是服務(wù)器的實(shí)例模式。COM+組件服務(wù)器,可以有以下三種實(shí)例模式,默認(rèn)為Mulitple Instance方式。1、Internal:供COM對(duì)象內(nèi)部使用,不會(huì)響應(yīng)客戶端的請(qǐng)求,只能通過COM對(duì)象內(nèi)部的其他方法建立。2、Single Instance:

43、不論當(dāng)前系統(tǒng)內(nèi)部是否存在相同COM對(duì)象,都會(huì)建立一個(gè)新的程序及獨(dú)立的對(duì)象實(shí)例。3、Mulitple Instance:如果有多個(gè)相同的COM對(duì)象,只會(huì)建立一個(gè)程序,多個(gè)COM對(duì)象的實(shí)例共享公共代碼,并擁有自己的數(shù)據(jù)空間。 tmApartment是COM+服務(wù)器的線程模式。COM+服務(wù)器的線程模式一下五種:1、Single:僅單線程,處理簡(jiǎn)單,吞吐量最低;2、Apartment:COM程序多線程,單個(gè)COM對(duì)象處理請(qǐng)求單線程;3、Free:一個(gè)COM對(duì)象的多個(gè)實(shí)例可以同時(shí)運(yùn)行。吞吐量提高的同時(shí),也要求對(duì)COM對(duì)象進(jìn)行必要的保護(hù),以避免多個(gè)實(shí)例沖突;4、Both:同時(shí)支持Aartment和Free

44、兩種線程模式。5、Neutral:只能在COM+下使用。在這個(gè)函數(shù)里面,可以看到建立工程的時(shí)候所選擇的線程模式等服務(wù)器特征最終都是以代碼的形式控制和實(shí)現(xiàn)的。前面已經(jīng)提到了TAutoObjectFactory類,它是創(chuàng)建TAutoObject類對(duì)象的工廠類。TAutoObjectFactory的create函數(shù)遞歸調(diào)用了它的父類的工廠類的create函數(shù),并進(jìn)行初始化。這個(gè)函數(shù)提供了創(chuàng)建COM+對(duì)象所需要的所有的信息。在TComObjectFactory.Create函數(shù)中,有這么一句話:ComClassManager.AddObjectFactory(Self)。這個(gè)函數(shù)的作用,就是將創(chuàng)建的COM+對(duì)象加入到COM的管理器中進(jìn)行管理。 初始化程序又是怎么被調(diào)用的呢?客戶端調(diào)用CoClass的create或者CreateRemote函數(shù)用來返回一個(gè)COM+對(duì)象的接口。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論