细节决定成败:一个公共类库
CLI缺憾之一:公共體系結(jié)構(gòu)定義
Hierarchical Structure是一種應(yīng)用極其廣泛的數(shù)據(jù)結(jié)構(gòu)(樹結(jié)構(gòu)),其意義完全可以和Collection結(jié)構(gòu)相提并論。可是.Net Framework的CLI提供了Collection卻沒有提供Hierarchy。絕大部分情況下,你可以通過其它方式(例如配合集合再定義一些接口)來實(shí)現(xiàn),但是不能否認(rèn)這些實(shí)現(xiàn)都很受局限,并且存在一些明顯不合理的依賴。我在實(shí)現(xiàn)業(yè)務(wù)邏輯的時候,想通過某種方式通知表現(xiàn)層通過Hierarchy的方式來處理。而表現(xiàn)層是通過一個實(shí)現(xiàn)Hierarchical Structure的公共控件實(shí)現(xiàn)的(這樣的情況在.net下非常普遍),沒有理由要依賴我特定的業(yè)務(wù)層。
我所期望的Hierarchy服務(wù)至少應(yīng)該提供兩個接口和一個基類:
- INode:節(jié)點(diǎn),標(biāo)定節(jié)點(diǎn)的標(biāo)識、上級節(jié)點(diǎn)及子節(jié)點(diǎn)集合;
- INodeList:節(jié)點(diǎn)集合,可以認(rèn)為是IList的派生接口,除完成IList的所有功能外,還必須負(fù)責(zé)與父節(jié)點(diǎn)的連接。
- NodeCollectionBase:節(jié)點(diǎn)集合基類,可以認(rèn)為是CollectionBase的包裝版本,完成集合管理及父節(jié)點(diǎn)的標(biāo)識。
之所以我覺得這個服務(wù)應(yīng)該由CLI提供,很簡單的理由,這些結(jié)構(gòu)應(yīng)用非常普遍,完全應(yīng)該是一種公共的、基本的依賴。
我設(shè)計的Hierarchy服務(wù)在Kanas.Hierarchizations命名空間,除了以上接口和基類外,還提供了一個服務(wù)類和兩個將普通類型包裝成Hierarchical結(jié)構(gòu)的接口。
- Hierarchy服務(wù)類:提供了大量Hierarchy的算法,例如求寬度、求深度、求子節(jié)點(diǎn)數(shù)、求級別等等,另外還通過相關(guān)的包裝器接口生成Hierarchy體系的功能。
- IHierarchizer接口:提供將普通類包裝成INode的接口。
- IHierarchizable接口:提供普通類的線型集合實(shí)例及IHierarchizer接口的實(shí)現(xiàn)。
應(yīng)用場景:菜單,可視化的樹視圖,目錄體系、組織結(jié)構(gòu)、財務(wù)科目、詞典類,等等等等。
?
CLI缺憾之二:可視化框架
.Net提供的PropertyGrid是Visual Studio.net設(shè)計時支持的基礎(chǔ),為此,Microsoft為.Net的PropertyGrid提供了極其強(qiáng)大的擴(kuò)展能力。ComponentModel命名空間下的很多類型及屬性都提供了對編輯器、設(shè)計器、類型轉(zhuǎn)換器的支持。不過很顯然地,其中存在一些設(shè)計漏洞,例如沒有提供足夠的抽象,直接導(dǎo)致了某些不必要的局限。其后果一是所有提供設(shè)計時支持的Attribute都幾乎只能應(yīng)用于PropertyGrid,讓運(yùn)行時類型背負(fù)設(shè)計時支持的包袱顯然有種職責(zé)不清的嫌疑;其后果二是PropertyGrid只提供了下拉和彈出兩種模式的類型編輯,當(dāng)然目前是夠用的,但不能保證任何時候都夠用。
現(xiàn)如今我就遇到這個問題。TypeConverterAttribute和TypeEditorAttribute這兩個屬性就必須進(jìn)行Web架構(gòu)的擴(kuò)展而不是完全依賴WindowsForms。直觀的感覺是,設(shè)計時特征依賴運(yùn)行時特征是合理的,相反則不合理。當(dāng)然,設(shè)計時Attribute在運(yùn)行時沒有任何意義,也不會給運(yùn)行時帶來額外的性能問題。可是,為什么不能將設(shè)計時Attribute設(shè)計成更好的模型?例如可以設(shè)計成侵入式或者附加式。
我設(shè)計的對象設(shè)計時服務(wù)在Kanas.ObjectScope命名空間,采用的是附加式策略。當(dāng)需要在運(yùn)行時使用類似設(shè)計時服務(wù)的功能時便可以更靈活地使用。這個服務(wù)是基于一個Xml的Schema,將對象的探查或展示方案部署到相應(yīng)的配置文件中,運(yùn)行時根據(jù)這些配置獲得設(shè)計時支持。與ComponentModel的設(shè)計思想一樣,這一套服務(wù)應(yīng)該包括公共定義(契約)、配置提供器(服務(wù))、對象展示及編輯(消費(fèi))三部分。
定義部分包括一個XSD規(guī)范及其對應(yīng)的對象模型、一個數(shù)據(jù)轉(zhuǎn)換器接口和一個編輯器接口。配置提供器包括一個配置閱讀器基類(設(shè)計成Component以備設(shè)計時使用)、三個不同配置方案的實(shí)現(xiàn)(分別實(shí)現(xiàn)對Xml配置文件、Xml配置資源和全局配置文件節(jié)三種配置方式)。對象的展示是表現(xiàn)層的事情,本套服務(wù)不需要實(shí)現(xiàn)。不過在本套服務(wù)中,通過配置的數(shù)據(jù)轉(zhuǎn)換器接口實(shí)現(xiàn)了從對象集合到數(shù)據(jù)集的自動轉(zhuǎn)換,分別是Kanas.Common命名空間中的TypeBoundDataTable和ListDataTable。兩者的區(qū)別是:前者不依賴Scope方案,單純實(shí)現(xiàn)ICollection到DataTable的轉(zhuǎn)換;后者是前者的派生,可以通過Scope方案影響DataTable的生成。
當(dāng)然,這個方案也存在很大的局限,甚至顯得非常粗糙。不過就其擺脫消費(fèi)依賴來說還是有意義的。當(dāng)然,眼下只實(shí)現(xiàn)了對Property的配置,缺乏對實(shí)現(xiàn)對invocation及event hook的擴(kuò)展,也缺乏對更詳細(xì)的可視化屬性(例如ComponentModel中的CategoryAttribute)的定義。
這就是這個簡陋的schema:
下載這個實(shí)現(xiàn),如果需要源碼請來信索取。
總結(jié)
以上是生活随笔為你收集整理的细节决定成败:一个公共类库的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2005年存储市场关键词TOP10
- 下一篇: 《中国编程挑战赛--资格赛》赛题及解答