新框架正在逐步完善,可喜可賀的是基礎服務部分初具模樣了,給大家分享一下 由於基礎服務涉及面太廣,也沒開發完,這篇只介紹其中的類型轉化部分,命名為類型轉化基礎服務,其實就是基礎服務模塊的類型轉化子模塊 說到類型轉化必須要弄清楚.net的類型,類型都不清楚何來類型轉化 1、Primitive類型 1.1 ...
新框架正在逐步完善,可喜可賀的是基礎服務部分初具模樣了,給大家分享一下
由於基礎服務涉及面太廣,也沒開發完,這篇只介紹其中的類型轉化部分,命名為類型轉化基礎服務,其實就是基礎服務模塊的類型轉化子模塊
說到類型轉化必須要弄清楚.net的類型,類型都不清楚何來類型轉化
1、Primitive類型
1.1 這個概念估計很多人都沒聽說過,Primitive不是一個新類型,而是.net類型中最基本的一種分類,是基元類型的意思
MS將類型分為三類:Primitive(基元類型)、Complex(複合類型) 和 Collection(集合類型),Type 提供了IsPrimitive 屬性
1.2 哪些類型屬於Primitive呢?
參考鏈接:http://msdn.microsoft.com/en-us/library/system.type.isprimitive(v=vs.110).aspx
”The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.“
1.3 看到這裡還是挺失望的,我們常用的類型Decimal和String並不含在內
有的同學可能說,別說那兩個了,裡面就除了Char和Double其他都沒用過;老實說MS真的把.net程式員徹底慣壞了
其實Boolean就是我們常用的bool,Int32就是int,Int64就是long,Single就是float
1.4 Primitive類型有什麼用呢?
Primitive是基元類型,可以這樣理解,其他類型都是由Primitive類型構成的或者衍生的,.net對Primitive支持最好,"有些地方"對於非Primitive類型支持不好,可能造成"靈異"事件(對於一般的項目是很難碰到的,如果你能碰到,說明你對.net鑽研的比較深了,普通的工程師就更不要嚷嚷說.net類型有缺陷不敢用之說,最多底層框架開發者或者架構師小心一點)
這裡就不展開了
2、IConvertible類型
IConvertible並不是新維度的類型類別,IConvertible是MS定義的一個介面,我這裡講的IConvertible類型特指Ms定義的基本類型中繼承了該介面的類型
我來稍作解析一下,繼承了IConvertible的類型非常強大,可以方便的轉化為常用的這15種類型,也正是這15種類型繼承了IConvertible介面
也就是這15種類型可以方便的相互轉化(其實不一定的,有些轉化是會出錯的)
IConvertible類型轉化具有高度的擴展性,可以傳一個格式化的參數(IFormatProvider)
3、"基本"類型
這裡是我定義的”基本類型“,我認為有這些類型就足夠開發使用,框架對此之外的類型不予"支持",或者這些類型優先支持
包含類型列表:bool、byte、char、decimal、double、float、int、long、string、DateTime、byte[]
註1:在現在記憶體這麼便宜的時代,我認為短數據類型的作用不大,短數據類型都使用int就好了
註2:我也不喜歡使用無符號類型,所以又省略了一大批類型,對於數字類型Ms使用==0表示"邏輯空",我使用<=0表示"邏輯空",後面還有相關例子
註3:這樣做也是情非得已,類型太多了,其排列組合更多,好在本框架是可擴展框架,使用本框架的時候可以自己擴展支持的類型,當然也可以開發一個類型擴展的組件(類庫),需要的時候自己註冊進去
現在開始演示類型轉化基礎服務
一、類型太多,這裡先拿int類型測試
1、字元串轉int
2、不同數字類型轉化為Int
這裡我要多嘮叨一句,我前面說過對”基本類型“以外的不予支持,其實是不"支持"轉化為這些類型,這些類型轉化為”基本類型“是沒有問題的
另外,會嘗試IConvertible的類型相互轉化,如果Ms支持的很好的IConvertible轉化.這裡也沒道理不支持的
3、object轉化為int
以上例子可以看出,基本類型轉化完全沒有問題,其實在主框架,我也不打算預設實現複雜自定義類型的轉化,這個留給擴展實現
有人可能會說你上面的這些功能So easy,實現過類似功能的多如牛毛,不過是多造個輪子而已。確實,基本類型轉化實現簡單,但是這裡要強調,我做的是可擴展框架,可擴展是亮點,而且非常容易擴展
二、擴展自定義類型轉化為int的例子
1、先看自定義類型代碼
非常簡單還是解讀一下,定義了兩個類型,customObj明顯是個模型(Model)類,customConverter有一個方法傳入一個customObj對象返回一個int值
2、再看對象轉化代碼
首先我們看結果,是我們預期的效果,和customConverter的Get方法的效果一致,但是我們沒有直接調用customConverter.Get,甚至好像和customConverter類型都沒什麼關係
這裡有幾個關鍵因素,其一是GlobalServices.Convert方法是怎麼運行的;其二是GlobalServices.CreateContainer()是什麼鬼
三、源碼解析
1、GlobalServices.Convert方法解析
這個類型轉化還是挺複雜的,挑主要的來解讀
1.1 TryConvert是嘗試類型轉化,如果轉化失敗可以換一種方法再做
這種方式在本框架中有大量應用,其實就就形成一個”策略鏈“,每個”策略“判斷一個這個問題自己是否是自己可以處理的類型,不能處理,下一個策略繼續,這樣非常便於擴展
在TryConvert中先調用個介面IEntityConvert,轉化失敗再調用IEntityAccess用來轉化
這裡有一個特別重要的事情,就是這個介面的對象從哪裡來,這裡是來自一個容器對象,這裡很清楚的看到本框架的一個擴展點,只要往容器裡面添加"策略"就可以增強本框架的類型轉化功能,這是我為什麼說主框架不打算實現複雜的類型轉化,真的非常容易擴展
1.2 再看Convert主方法
A:先按當前類型嘗試轉化
如果策略庫(容器註冊)裡面有當前兩種類型轉化的策略,性能是最好的,優先執行
B:轉化失敗判斷當前對象是否為空
對象為null,放棄轉化,直接返回預設值
C:Transform.TryConvertByType
這個簡單就是強制類型轉化,如果T是S的基類,這個時候就可以直接轉化過去,也是非常安全的
D:再嘗試IConvertible轉化
前面說到系統的IConvertible定義了15種基本類型的相互排列組合轉化,而且還可以使用IFormatProvider自定義轉化,這就是一個強大的轉化機器,不能不試
E:再檢測返回類型是否為string,如果是string直接調用對象的ToString()
F:最後嘗試把s對象轉化為字元串,然後把字元串轉化為目標類型(T)對象
其實這裡把字元串作為基本數據格式,相當於與對s對象序列化為字元串,然後把字元串反序列化為T類型對象,也不怪我怎麼用,.net所有類型都有一個ToString()方法,所以string是個不錯的中間類型
功能是不是非常強大,也非常有別於很多類型轉化工具,上來先反射,獲取類型元數據,然後調用屬性和欄位,現在還沒做測試,我這種方式可能會有明顯的性能優勢,但是性能現在不是我最想考慮的問題,我現在考慮的是怎麼可以非常簡單的擴展
2、GlobalServices.CreateContainer()是什麼鬼
CreateContainer定義
A:從上面可以看出GlobalServices.CreateContainer就是一個再普通不過的容器,預設實例的容器名是GlobalServices
B:前面有提到容器是可以擴展的,只要我們使用的容器支持(比如Unity、Spring.net等),我們完全可以使用配置文件來擴展類型轉化,還可以使用非常炫的IOC和AOP等特性
C:說到這裡,現在"業界"有幾個類型轉化工作可以做到?我稍微看了一個現在非常流行的Automapper,自定義映射確實沒問題,但是映射過程還可以通過配置文件擴展或者IOC和AOP的我沒見識過,如果有人看到過請告知,我要好好學習學習
D:早期看過這篇文章的可能發現,變化很大,我把GlobalServices由靜態類修改可以實例化的形式,這樣就允許我們創建多套服務配置管理對象(使用子容器技術,繼承預設服務並覆蓋少數服務),進一步提高可擴展性
3、其實GlobalServices容器和其他容器還是有點區別的,繼續深挖源碼
這裡有一個不起眼的地方加了一行代碼,給GlobalServices容器”吃小竈“
不挖不知道,一挖嚇一跳,有一種”柳暗花明又一村“的感覺
哈哈,我就說我要對每個容器做包裝,”居心不良“吧;哈哈,這樣說太難聽了,一句話"還是為了更好的擴展"。
4、沒辦法了,還得繼續挖GlobalServices.CheckServices
這裡可以看到框架支持的"基本類型",把這些轉化策略都註冊到容器中,主要是擔心容器註冊的服務不夠用,把不足的基本類型轉化服務都註冊上
當然如果容器中已經存在同類型的"服務",這裡的註冊是會忽略的
同樣,就算是這裡註冊的服務,如果覺得不好用,也可以在外面重新註冊並覆蓋
還有一點,前面截圖可以明顯看出"基礎服務模塊"的基本樣子,但是除了”類型轉化子模塊“外,其他子模塊都還沒開發出來
四、擴展性演示
1、邏輯空(int轉bool)
前面有提高,我是把>0為true的,<=0為false,我一直用的很方便,我叫做"邏輯空",但是ms並不是這樣處理的,如果有的團隊還是希望按ms的規則怎麼辦,擴展啊
2、把上例中的註釋打開就切換為ms模式(==0為false)
上面的結果就是ms模式了
3、現在來看一下是怎麼擴展的
以上代碼很清楚,擴展很簡單,獲取服務配置的容器,註入服務並覆蓋原服務,就完成了擴展
暫時就挖到這裡,還遠沒有完全詮釋”類型轉化基礎服務“的可擴展性的全貌,但是該模塊還在測試和完善中,只好有空再補了