1. 程式人生 > >C# ORM中反射與泛型的交叉應用

C# ORM中反射與泛型的交叉應用

好久沒有寫文章了,終於找到工作,抽空寫一下冒個泡。

問題

最近遇到一個這樣 ORM 的問題,一個返回型別為 List 泛型方法中,需要做到根據條件訪問資料庫,並且把得到的結果存入 List 中返回。

由於只是以前學過一段時間的 C#,而且反射一直個人認為是各中難點,加上泛型,這篇文章純屬個人紀錄,如有錯誤,望各位大佬指正。

分析

根據條件訪問資料庫 ==> 遍歷獲取到的 reader 物件 ==> 建立泛型例項以及泛型 List,並且對例項賦值存入 List ==> 遍歷完成,返回當前的 List

從上面的幾個步驟中我們可以發現,難點就是在於這個泛型例項的建立以及它的屬性賦值。我們可以通過 Activator 的CreateInstance(type) 方法建立,然後通過 type.setValue(object,value,index) 來設定對應的屬性值,至於如何匹配這些屬性值,我們就通過 ORM 中來對映獲取到對應的特性值與資料庫欄位的匹配。這樣問題就解決了。

解決方法

這裡分為幾個步驟,

  1. 獲取到資料庫的返回(ps:這個比較簡單我就不多說了,具體可以直接百度,狗狗都有很多)
  2. 獲取到對應的泛型的型別
    這裡是通過 typeof() 方法
  3. 通過獲取到的型別由 Activator 類的 CreateInstance(type) 方法建立 object 例項
  4. 通過 type 獲取到此例項的屬性列表
  5. 遍歷屬性列表,並與 資料庫 中的屬性對比匹配,得到匹配成功的特性資訊。
  6. 判斷特性資訊,為空就跳過,不為空就通過 setValue(object,value,index) 方法設定屬性的對應值,並新增到 List 中。

程式碼

private
const string SELECT = "SELECT * FROM dbo.Alvin "; public static List<TEntity> Query<TEntity>(string condition) { using (var conn = SqlHelper.Instance.GetConnection()) { var reader = SqlHelper .Instance .ExecuteQuery(conn, SELECT + condition, new
List<SqlParameter> { }); List<TEntity> list = new List<TEntity>(); //獲取到泛型的型別 Type type = typeof(TEntity); //通過反射由型別建立對應object例項 object o = Activator.CreateInstance(type); //通過型別獲取到有的屬性 var infos = type.GetProperties(); while (reader.Read()) { //Console.WriteLine("infos 數量:{0}",infos.Length); foreach (var info in infos) { //Console.WriteLine("info 不為空"); //獲取到屬性對應的特性資訊(這裡就做了匹配) object[] ob = info.GetCustomAttributes(typeof(FieldAttribute), false); if (ob != null) { //通過反射設定對應的屬性值,o代表與o繫結 info.SetValue(o, reader[((FieldAttribute)ob[0]).Fields], null); //Console.WriteLine("結果是:{0}", reader[((FieldAttribute)ob[0]).Fields]); } } //新增到list中 list.Add((TEntity)o); } return list; } }

這裡 ORM 就不貼上了,這裡 Record 類是完全匹配資料庫裡表段的,但是 RecordLess 是不完全匹配,暫時只測試到這麼多,還有一類就是啥都沒有匹配的還沒測試過,

結果

RecordLess

RecordLess

Record

Record