1. 程式人生 > >Elite Container DELPHI下的一個輕量級IoC對象容器

Elite Container DELPHI下的一個輕量級IoC對象容器

映射 覆蓋 都是 特點 客戶端 難度 反饋 實體 get

一、簡介:

Elite Container是DELPHI下的一個輕量級IoC對象容器(IoC:Inverse of Control,反轉控制)。它是參考了Java中的Spring框架(主要是配置文件的寫法),並結合DELPHI的特點來構建的。相比Spring的對象容器,它提供的功能更為精簡常用(如對象延遲創建、對象屬性自動註入等),降低了學習的難度,並且提供了很多擴展點,你只需簡單地寫一個插件實現類,並在配置文件中進行簡單配置,就可以讓Elite Container擁有你的自定義功能!

Elite Container主要擁有以下的一些特性:

1、無論使用或不使用BPL,都可以用Elite Container來構建你的程序(但不建議用純DLL,因為各DLL中,同一個類的類型信息是不同的,不熟悉相關知識的話,有可能會帶來一些問題,而這本身並不是Elite Container的問題)
2、支持多種屬性註入類型,如直接值、枚舉、集合、StringList、ObjectList等。其中StringList這種註入方式,在解決鍵值對配置時非常有用,詳細請參看相關例子
3、支持構造函數註入。但由於Delphi

的元信息不夠完備,有時需要寫一個構造函數調用類(寫法很簡單),才可讓容器正確調用該類和其子類的構造函數,詳細請看相關例子另外由於構造函數註入有可能會引起循環註入的問題,因此建議盡量使用屬性註入來表達對象的依賴關系,不得已的時候才使用構造函數註入
4、支持對象配置的繼承。省去配置子對象時,又要把父對象的屬性配置重新拷貝一遍,既麻煩又難維護。
5、支持對象屬性的自動註入。如果你的屬性命名滿足一定規則,便可以利用自動註入來省去大量的配置書寫
6、支持配置文件的引入,提高配置文件的可重用性
7、支持多種對象的生命周期配置(對於無狀態的管理類,如邏輯層,單例生命周期是最常用的)
8、支持對象的別名配置
9、增強的對象註冊機制,可註冊非TPersistent為基類的類(常見的如TInterfacedObject),並且容器可以區分不同單元的同名類
10、兼容使用Delphi
的RegisterClass來註冊類的遺留模塊
11、大量的自定義插件擴展點。你可以自定義自己的屬性註入配置方式、構造函數註入配置方式、對象配置引入方式、對象生命周期管理方式、對象屬性自動註入方式等
12、支持對象的延遲創建。以免容器初始化時,會自動實例化一些需要花費大量時間來創建,而又很少用的類。
13、大量的可編程接口。你甚至可以自己寫一個用INI、或數據庫來進行配置的IoC容器!

借助Elite Container和Ioc思想,你可以更輕易地構建出具有松散耦合、重用度高的應用程序。它的核心思想就是拆分功能的接口和實現,上層只依賴於下層的接口,然後通過Elite Container的配置,把不同的實現類註入到該接口中,達到更換功能,也就是復用已有代碼的目的。設計人員可以真正地發揮好自己的面向對象思想和相關設計模式,來架構企業級的應用程序,而無需象以前那樣,在Delphi
中用起面向對象總有點捉襟見袖的感覺。

DEMO下載地址:http://download.csdn.net/source/1891434

二、使用Elite Container的典型開發步驟:

1、新建項目,在項目選項中選擇“build with runtime packages”,去掉所有的默認包,然後選擇EliteContainerD7
2、建立應用程序的領域(如對象實體、邏輯處理、接口服務等)
3、用XML文件來配置這些對象
4、引用elXMLConfigurateContainer單元,聲明一個IelObjectContainer類型的接口變量
5、給這個接口創建一個TelXMLConfigurateContainer的實例,把這個XML文件的路徑(相對或絕對路徑均可,構造函數有參數指定),作為參數傳入到構造函數中
6、TelXMLConfigurateContainer創建的時候,會自動初始化生命周期配置為"singleton",並且不是延遲創建的對象
7、現在可以根據配置文件所配置的對象ID或別名,從容器中獲取已配置好的對象或接口了
8、調用所獲取的對象或接口,來完成程序的功能

三、DEMO目錄說明:

Bin 各個例子的可執行程序
Bin\Config 各個例子所用到的配置文件
Lib 各個例子用到的dcp文件,需要在項目設置的"Build with runtime packages"中引入
Source 各個例子的源代碼。共26個例子,用於詳細介紹Elite Container的特性。請務必結合源代碼、配置文件和可執行文件來理解,這樣才能達到演示的目的。如果要編譯例子源代碼的話,請把Lib目錄添加到Delphi的Library Path下,並修改下項目的輸出路徑。

四、DEMO簡要說明:

例1:示範了容器最基本的功能。如何獲取一個配置好的對象,包括以對象形式獲取(GetObj),和以接口的形式獲取(GetIntf)。

例2:示範了容器最基本的功能。與例1不同的是,這個例子中,類被封裝了在BPL當中。這種方式是項目實際開發時,最常用的方式(以便重用業務邏輯)。註意在配置對象的時候,對象的class配置,還要加上類所在的bpl文件,然後還要在程序中對類進行註冊。

例3:示範了如何把直接值(字符串、整數等)註入到屬性中。這種方式常用於利用配置來改變對象的某些初始狀態,例如可以把數據庫鏈接串以這種方式註入到對象中,以便不用重新編譯也能改變程序的數據庫鏈接。

例4:示範了如何把枚舉或集合註入到屬性中。強大的是,配置中,你既可以寫枚舉的字符串名稱,也可以寫枚舉的整數值。

例5:示範了如何把其它配置的對象註入到屬性中。屬性可以是對象類型,也可以是接口類型(假如被註入的對象,實現了該接口)。這是最常用的註入方式,例如把數據訪問對象註入到業務邏輯對象中,以便讓業務邏輯對象訪問數據庫。

例6:示範了如何配置一個StringList對象,並把它註入到屬性中。從配置文件中可以看到,配置的方式非常多。其中KeyValueList和ObjectRefList這兩個屬性的配置都采用類鍵值對的形式,這種形式在解決映射關系時,是很常用的。

例7:示範了如何配置一個ObjectList對象,並把它註入到屬性中。註意,ObjectList的OwnsObject參數是默認被設置為false的,也就是說,釋放這個ObjectList,不會釋放裏面的對象。因為Elite Container的單例聲明周期是最常用的,因此對象的生命周期應由容器來管理,不應該在ObjectList釋放的時候就釋放。不過也可以直接把ObjectList配置成管理生命周期,例如它裏面的對象的生命周期被配置了為"prototype"的時候。你需要清楚地知道對象的生命周期是如何被管理的,才可正確使用好這種註入方式。

例8:示範了如何配置一個InterfaceList對象,並把它註入到屬性中。

例9:示範了對象屬性自動註入的功能。可以設置為根據屬性名稱("T"加上屬性名來作為對象ID)、屬性類型或自動模式,來嘗試從容器中獲取對象。自動註入會作用於沒有手動配置,不是只讀,類型是對象或接口的那些屬性上。自動註入默認是關閉的(值為"false"),而按屬性名稱,是最常用的自動註入模式。

例10:示範了繼承父對象的屬性配置。才能夠配置文件可以看到,TMyObjectB的Count、Text、Day這三個屬性的值,均繼承了TMyObjectA中的設置。強大的是,你還能進行屬性配置的覆蓋,可以看到TMyObjectB中Day的值是wdTuesday,而不是TMyObjectA中配置的wdMonday。

例11:示範了構造函數註入。註意要配置構造函數參數的類型,常見的取值有string、integer、float、boolean、string、enum、set、object、interface等。

例12:示範了對象配置的引入。通常我們可以給各個組件寫獨立的配置文件,然後主程序引入這幾個組件的配置文件即可。這樣便重用了組件的配置文件了。註意,如果對象的配置量非常巨大,可以通過設置lazy="true"來延遲載入該配置文件。

例13:示範了對象的生命周期配置。默認的三種生命周期是:單例"singleton",該對象的實例由容器來管理(不要自己釋放掉它),並且每次獲取都是得到同一個實例,這種生命周期是默認的生命周期;原型"prototype",容器只負責對象的創建,而不負責實例的釋放,你需要自己來管理它的生命周期;線程單例"per-thread",本質也是單例模式,但是每條線程裏都會有一個不同的單例。

例14:示範了對象的別名聲明。此功能常用於整合資源,例如幾個組件分別聲明了數據庫鏈接的對象ID,我可以通過聲明別名,把這幾個數據庫鏈接的對象ID都指向同一個對象,那麽就實現了幾個組件用同一個數據庫鏈接了。

例15:示範了完成註入後,讓對象進行初始化處理。通常可以在這裏檢查對象的屬性有被註入,因為寫漏配置的現象有時還是難以避免的。

例16:示範了如何兼容使用RegisterClass來註冊類的老模塊。其實使用上是完全一樣的,沒任何特殊之處。

例17(進階功能):示範了如何註入DELPHI自帶的類。要註意的是,要手動對這些類進行下註冊,其它就沒什麽特殊了。

例18(進階功能):示範了如何獲取不同單元中的同名類。配置中,class註意要加上類所在的單元名。

例19(進階功能):示範了自定義屬性註入的處理。你需要分別寫一個屬性值識別器和屬性值註入器,然後把它在配置中進行配置即可。可以看到,例子的配置中,屬性出現了自定義的類型"path"。

例20(進階功能):示範了自定義構造函數註入的處理。你需要分別寫一個構造函數參數值識別器和構造函數參數值註入器,然後把它在配置中進行配置即可。可以看到,例子的配置中,構造函數參數出現了自定義的類型"owner-selector"。

例21(進階功能):示範了如何自定義對象配置引入機制。例子中把對象的配置封裝在了DLL中,對配置起到了簡單的保護作用。因為Delphi被大量使用在客戶端程序中,這跟Java是有區別的。因此這可以說是具有Delphi特色的一個很有用的擴展點。

例22(進階功能):示範了自定義對象的生命周期管理方式。

例23(進階功能):示範了自定義的對象屬性自動註入器的編寫。

例24(進階功能):示範了如何寫構造函數調用器。當出現以下兩種情況時,你才需要為類寫一個構造函數調用器:基類的構造函數不是虛函數,而你在子類中又聲明了該構造函數;基類的構造函數雖然是虛函數,但是在子類中,你對它進行了重新聲明,或者提供了重載的版本。一般調用器的邏輯,需要檢查參數的個數、簽名,根據重載的版本,判斷參數是否存在,參數類型是否正確等。

例25(進階功能):示範了對象屬性的延遲獲取。例子中獲取TExample時,三個屬性均是沒值的,只有在它們被訪問到的時候,才用容器中獲取所配置的對象。這樣便大大增加了TExample的獲取速度(這三個屬性所配置的類,為了演示需要,在創建時都人工sleep了一段時間作為延遲)

例26(進階功能):示範了如何註冊不是TPersistent作為基類的類。

五、其它說明:

Elite Container可支持Delphi 7以上的任何版本,目前暫只提供D7的版本供試用。另外放出此DEMO,主要的目的是為了能及時收集大家的反饋意見而已,容器本身不可以避免尚會存在一些問題,如內存泄露、缺乏線程保護等,暫時請勿用於實際項目中,否則後果自負。

Elite Container DELPHI下的一個輕量級IoC對象容器