承接著上一篇, 這一篇主要以堆棧的方式來演示一下, db數據轉換到類中去的一個過程.
一、先看第一張圖
程序在運行到176行(上一篇貼出的代碼)的時候, 就會出現上圖中的第一個棧.
那在此之前, Dapper又做了些什麼呢? 拋開Dapper的這種OpCodes的實現方式來說, 我們自己用代碼去轉換, 實現思路如下:
1. 首先肯定是要獲取, 從db讀取出來的那麼多列中, 有哪一些是需要轉換的吧, 如果是select * , 那會讀取出所有的列, 但是我本身並不需要那麼多列, 而且, 我接收的類, 本身可能並沒有那麼多的列, 所以, 首先確定有哪些列需要轉換, 以及這些列從db中讀取出來是什麼類型的.
2. 當確定好有效的列之後, 就可以獲取類中的構造函數, 已備創建類的時候使用. 在獲取構造函數的時候, 當然是越簡單的構造函數越好.(Dapper中會優先檢測標有ExplicitConstructor屬性的構造函數, 然後獲取構造函數的參數, 然後初始化參數), 然後就是把這個類new出來.
3. 到現在, 我們其實就已經能知道source data type 和 target property/feild type了, 既然已經兩邊的類型都已經知道, db數據已經准備好, target class也已經new好了, 就可以來實現轉換了, 根據類型的不同, 來使用不同的轉換. 值得一提的事, 如果 target class中, 含有自定義類的屬性或者字段, Dapper是不會繼續轉換的, 直接給了個null就了事了. 其實Dapper中, 也是可以實現此功能的, 這部分以後再說.
那麼現在回到Dapper裡來, 其實他做的工作也是這樣子的, 順序可能稍有不同, 1,2的順序是可調的. 只是他實現的方式稍有不同而已. 條條大路通羅馬, 目的地都是相同的, 不同的是途中的風景.
二、接著第二張圖
上圖中的第一個棧, 是執行完 181行 代碼之後, 出現的情況, 180行, 181代碼的意思, 其實就是把 reader[index]復制一份到 loc2中, 這個loc2就是前面(161行)聲明的, 類型為object的本地變量, 所以, 從堆棧的情況來看, 180行未執行前, 和181行執行完之後的堆棧是一樣的. 所以我就不畫了.
在執行Unbox_Any之前, 是已經知道source type和target type了, 並且已經經過判斷, 是否能夠轉換, 然後再通過Unbox_Any來轉, Unbox是拆箱操作, Unbox_Any是拆箱成你需要的類型
上面這兩幅圖就是正常情況下(int, string, datetime, double等)的堆棧變化過程了, 應該還是比較能輔助理解的了.