C# 通過反射初探ORM框架的實(shí)現(xiàn)原理(詳解)
背景:
以前學(xué)的Java進(jìn)行開發(fā),多用到Mybatis,Hiberante等ORM框架,最近需要上手一個(gè)C#的項(xiàng)目,由于不是特別難,也不想再去學(xué)習(xí)C#的ORM框架,所以就想著用反射簡單的實(shí)現(xiàn)一下ORM框架的內(nèi)容,簡單的增刪改查,沒有用到多表之間的聯(lián)系。
反射:
Java和C#中的反射大體相同,主要是指程序可以訪問,檢測和修改它本身狀態(tài)或行為的一種能力,并能根據(jù)自身行為的狀態(tài)和結(jié)果,調(diào)整或修改應(yīng)用所描述行為的狀態(tài)和相關(guān)的語義。我的理解就是可以程序運(yùn)行時(shí)動(dòng)態(tài)的獲取對(duì)象的屬性和方法,并且可以進(jìn)行與之相關(guān)的調(diào)用。
首先看一下C#中反射實(shí)現(xiàn)方式:
獲取Type對(duì)象,反射操作都需要通過Type對(duì)象來進(jìn)行。
通過全限定名來獲取 Type tp = Type.GetType("TJCommon.Dao.Deriver");
通過類來獲取 Type tp = typeof(Int)
獲取到Type對(duì)象后我們可以通過其構(gòu)造方法來創(chuàng)建對(duì)象
調(diào)用無參構(gòu)造
// 獲取類的初始化構(gòu)造信息 ConstructorInfo ct = tp.GetConstructor(System.Type.EmptyTypes); // 調(diào)用不帶參數(shù)的構(gòu)造器 T newObj = (T)ct.Invoke(null);
調(diào)用有參構(gòu)造
//定義參數(shù)類型數(shù)組 Type[] tps = new Type[2]; tps[0] = typeof(int); tps[1] = typeof(string); //獲取類的初始化參數(shù)信息 ConstructorInfo ct2 = tp.GetConstructor(tps); //定義參數(shù)數(shù)組 object[] obj = new object[2]; obj[0] = (object)100; obj[1] = (object)"Param Example"; //調(diào)用帶參數(shù)的構(gòu)造器 ExampleClass Ex2 = (ExampleClass)ct2.Invoke(obj);
獲得所有公共字段
// 獲取到所有公共字段 FieldInfo[] arr = t.GetFields(); // 給指定的字段賦值 需要傳遞進(jìn)來一個(gè)對(duì)象 newObj f.SetValue(newObj, r[name]);
這里就介紹這幾個(gè)方法,通過反射可以獲得類中的所有信息,并且可以進(jìn)行調(diào)用,還可以打破封裝(不安全)
練習(xí)
下面就是通過反射將從數(shù)據(jù)庫中獲取到的結(jié)果集自動(dòng)封裝到Bean中。無需手動(dòng)封裝
public static T dataToObj(String str)
{
String strSql = str;
DataSet ds = SqlCompose.ExecuteSqlQuery(strSql);
Type t = typeof(T);
DataRow r = ds.Tables[0].Rows[0]; // 找到一行
FieldInfo[] arr = t.GetFields(); // 返回所有公共字段(public)
ConstructorInfo ct = t.GetConstructor(System.Type.EmptyTypes);
T newObj = (T)ct.Invoke(null);
if (r != null)
{
foreach (FieldInfo f in arr)// 遍歷所有字段
{
string name = f.Name;
Type type2 = f.FieldType;
if (r[name].GetType() != typeof(DBNull))
{
string typeName = f.FieldType.Name;
f.SetValue(newObj, r[name]);
}
}
}
else
{
newObj = default(T);
}
ds.Tables.Clear();
return newObj;
}
封裝到List
public static List<T> dataToList(String str)
{
List<T> list = new List<T>();
String strSql = str;
DataSet ds = SqlCompose.ExecuteSqlQuery(strSql);
Type t = typeof(T);
FieldInfo[] arr = t.GetFields(); // 返回所有公共字段(public)
ConstructorInfo ct = t.GetConstructor(System.Type.EmptyTypes);
foreach (DataRow dr in ds.Tables[0].Rows)
{
T newObj = (T)ct.Invoke(null);
foreach (FieldInfo f in arr)// 遍歷所有字段
{
string name = f.Name;
Type type2 = f.FieldType;
string typeName = f.FieldType.Name;
if (dr[name].GetType() != typeof(DBNull))
{
f.SetValue(newObj, dr[name]);
}
}
list.Add(newObj);
}
ds.Tables.Clear();
return list;
}
拼接字符串進(jìn)行insert操作
public static void inserByBean(string tableName, T target)
{
StringBuilder sql = new StringBuilder(); // 拼接的sql
sql.Append("insert into "+tableName+"(");
Type t = target.GetType();
PropertyInfo[] ps = t.GetProperties();
for (int i = 0; i < ps.Length; i++)
{
object obj = ps[i].GetValue(target, null);
if (obj != null)
{
string name = ps[i].Name;
if (i != ps.Length - 1)
{
sql.Append(" " + name + ",");
}
else
{
sql.Append(" " + name + "");
}
}
}
sql.Append(") values(");
for (int i = 0; i < ps.Length; i++)
{
object obj = ps[i].GetValue(target, null);
if (obj != null)
{
if (i != ps.Length - 1)
{
if (ps[i].PropertyType == typeof(string) || ps[i].PropertyType == typeof(DateTime))
{
sql.Append("'" + obj + "',");
}
else {
sql.Append("" + obj + ",");
}
}
else
{
if (ps[i].PropertyType == typeof(string) || ps[i].PropertyType == typeof(DateTime))
{
sql.Append("'" + obj + "')");
}
else
{
sql.Append("" + obj + ")");
}
}
}
}
string resultSql = sql.ToString();
SqlCompose.ExecuteSqlNonQuery(resultSql);
}
以上這篇C# 通過反射初探ORM框架的實(shí)現(xiàn)原理(詳解)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
WPF TextBox實(shí)現(xiàn)按字節(jié)長度限制輸入功能
這篇文章主要為大家詳細(xì)介紹了WPF TextBox實(shí)現(xiàn)按字節(jié)長度限制輸入功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
C#實(shí)現(xiàn)ComboBox控件顯示出多個(gè)數(shù)據(jù)源屬性的方法
這篇文章主要介紹了C#實(shí)現(xiàn)ComboBox控件顯示出多個(gè)數(shù)據(jù)源屬性的方法,實(shí)例分析了ComboBox控件的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
C#實(shí)現(xiàn)連接電子秤串口自動(dòng)稱重
這篇文章介紹了C#實(shí)現(xiàn)連接電子秤串口自動(dòng)稱重的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
C# log4net 日志輸出的實(shí)現(xiàn)示例
本文主要介紹了C# log4net 日志輸出的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別
C#靜態(tài)方法與非靜態(tài)方法的區(qū)別不僅僅是概念上的,那么他們有什么具體的區(qū)別呢?讓我們通過本文向大家介紹下C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別,一起看看吧2017-09-09
WPF使用DrawingContext實(shí)現(xiàn)二維繪圖
這篇文章介紹了WPF使用DrawingContext實(shí)現(xiàn)二維繪圖的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

