1. 概述反射 通過反射可以提供類型信息,從而使得我們開發人員在運行時能夠利用這些信息構造和使用對象。 反射機制允許程式在執行過程中動態地添加各種功能。 2. Type類的介紹 是BCL(基底類別庫)聲明的一個抽象類,所有它不能被實例化 對於程式中用到的每一個類型,CLR(公共語言運行時)都會創建一 ...
1. 概述反射
- 通過反射可以提供類型信息,從而使得我們開發人員在運行時能夠利用這些信息構造和使用對象。
- 反射機制允許程式在執行過程中動態地添加各種功能。
2. Type類的介紹
- 是BCL(基底類別庫)聲明的一個抽象類,所有它不能被實例化
- 對於程式中用到的每一個類型,CLR(公共語言運行時)都會創建一個包含這個類型信息的Type類型的對象
- 程式中用到的每一個類型都會關聯到獨立的Type類型的對象
- 不管創建的類型有多少個實例,只有一個Type對象會關聯到所有這些實例
2.1 Type類的部分常見成員
成員 成員類型 描述 Name 屬性 返回類型的名字 FullName 屬性 返回數據類型的完全限定名(包括命名空間名) NameSpace 屬性 返回包含數據類型聲明的命名空間 Assembly 屬性 返回聲明類型的程式集。如果類型是泛型的,返回定義這個類型的程式集 GetConstructor(), GetConstructors() 方法 返回ConstructorInfo類型,用於取得該類的構造函數的信息 GetEvent(), GetEvents() 方法 返回EventInfo類型,用於取得該類的事件的信息 GetField(), GetFields() 方法 返回FieldInfo類型,用於取得該類的欄位(成員變數)的信息 GetInterface(), GetInterfaces() 方法 返回InterfaceInfo類型,用於取得該類實現的介面的信息 GetMember(), GetMembers() 方法 返回MemberInfo類型,用於取得該類的所有成員的信息 GetMethod(), GetMethods() 方法 返回MethodInfo類型,用於取得該類的方法的信息 GetProperty(), GetProperties() 方法 返回PropertyInfo類型,用於取得該類的屬性的信息
3. 如何獲取Type類型
3.1GetType()和typeof() 方法 兩者都是返回Syetem.Type的引用。(private和protected修飾的成員也可以訪問到)
3.1.1 GetType()
1.GetType()是從Syetem.object中基礎的方法。
2.GetType()必須要通過類型的實例點出這個方法。
3.1.2 typeof()
1.typeof(xx)是公開的運算符。
2.typeof(xx)中xx只能是int,string 等類型及自定義類型,不能是實例。
3.2 不同點
1.GetType()返回的是Type(類型)
2.typeof(xx) 返回的是xx Class(類)的類型
1 //實例一個用戶類 2 User user = new User(); 3 //GetType()方法 4 Type getType = user.GetType(); 5 //typeof(xx) 方法 6 Type typeOf = typeof(User); 7 //判斷是否相等 8 if (getType == typeOf) 9 { 10 //這裡相等 11 Console.WriteLine("我在這"); 12 }
4.Type類方法
1: 一旦有了Type對象就可以使用GetMethodInfo()方法獲取此類型支持的方法列表。該方法返回一個MethodInfo 對象數組,MethodInfo對象描述了主調類型所支持的方法,他位於System.Reflection命名空間中
2: MethodInfo類派生於MethodBase抽象類,而MethodBase類繼承了MemberInfo類。因此我們能夠使用這三個類定義的屬性和方法。例如,使用Name屬性得到方法名稱。這裡有兩個重要的成員:
3: ReturnType屬性 :為Type類型的對象,能夠提供方法的返回類型信息 GetParameters()方法 :返回參數列表,參數信息以數組形式保存在PatameterInfo對象中。PatameterInfo類定義了大量描述參數信息的屬性和方法。這裡也列出兩個常用的屬性 :Name(包含參數名稱信息的字元串),ParameterType(參數類型的信息)。
//創建實例 Sublevel sublevel = new Sublevel(); //獲取類型 Type sublevelType = sublevel.GetType(); //獲取類型的方法列表 //BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public 這個有一個註意點 //實際上至少要有Instance(或Static)與Public(或NonPublic)標記。否則將不會獲取任何方法。 MethodInfo[] obj = sublevelType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); //遍歷所有的方法 foreach (MethodInfo item in obj) { //返回方法的返回類型 Console.Write(item.ReturnType.Name); //返回方法的名稱 Console.Write(" "+item.Name+"("); //獲取方法的返回參數列表 ParameterInfo[] parameterss = item.GetParameters(); foreach (var parameters in parameterss) { //參數類型名稱 Console.Write(parameters.ParameterType.Name); //參數名稱 Console.Write(" "+parameters.Name+","); } Console.WriteLine(")"); }
執行的結果,獲取了所有的方法,包括了方法的方法名稱,方法的返回類型,方法參數列表。
5.方法的使用
前面我們講了放的顯示,但是只能看到不能用就不好了呀!!!
5.1:GetMethods()方法的另一種形式
這種形式可以制定各種標記,已篩選想要獲取的方法。他的通用形式為:MethodInfo[] GetMethods(BindingFlags bindingAttr)BindingFlags是一個枚舉,枚舉值有(很多只列出4個吧)
- Instance:獲取實例方法
- NonPublic: 獲取非公有方法
- Public: 獲取共有方法
- Static:獲取靜態方法
GetMethods(BindingFlags bindingAttr)這個方法,參數可以使用or把兩個或更多標記連接在一起,實際上至少要有Instance(或Static)與Public(或NonPublic)標記。否則將不會獲取任何方法。del.GetType();
public static void Method<T>(T model) { //獲取泛性的Type類型 Type objType = model.GetType(); //獲取泛性的方法列表 MethodInfo[] mthodInfos = objType.GetMethods(); //迴圈方法 foreach (var item in mthodInfos) { //獲取方法的所有參數列表 var parameters = item.GetParameters(); //過濾沒用方法 //1:查看是不是有參數的方法 //2:查看這個方法的返回類型是不是我們想要的 //3:查看這個方法的返回類型是不是我們想要的 if (parameters.Any() && parameters[0].ParameterType == typeof(int) && item.ReturnType != typeof(void)) { //調用方法 object[] parametersObj = new object[] { 5 }; //調用實例方法 //第一個參數是我們的實體,後面是我們的參數(參數是一個數組,多個參數按照順序來傳遞,沒有參數可以為null) //如果我們的方法是一個靜態方法 ,這個參數可以為null (不是靜態的就會報錯) Console.WriteLine(item.Invoke(model, parametersObj)); } } }
6.DataTable轉Model(List)
在剛剛學.net 的時候,我們從資料庫查詢出一個DataTable的時候想要轉成Model或者LIst的時候我們需要手動的寫遍歷,超級麻煩(在沒有接觸MVC的時候我就是)
/// <summary> /// DataTable轉換 /// </summary> public class TransitionDataTable { /// <summary> /// DataTable轉換模型 /// </summary> /// <typeparam name="T">模型類型</typeparam> /// <param name="obj">模型</param> /// <param name="data">數據行</param> /// <returns></returns> public T DataSetBindModel<T>(T obj, DataTable data) where T : class, new() { T result = new T(); foreach (DataRow item in data.Rows) { result = assignmentClass(obj, item); } return result; } /// <summary> /// DataTable轉換List /// </summary> /// <typeparam name="T">模型類型</typeparam> /// <param name="obj">模型</param> /// <param name="data">數據行</param> /// <returns></returns> public List<T> DataSetBindList<T>(T obj, DataTable data) where T : class, new() { List<T> result = new List<T>(); foreach (DataRow item in data.Rows) { result.Add(assignmentClass(obj, item)); } return result; } /// <summary> /// DataRow 轉換成模型 /// </summary> /// <typeparam name="T">模型類型</typeparam> /// <param name="obj">模型</param> /// <param name="row">數據行</param> /// <returns></returns> private T assignmentClass<T>(T obj, DataRow row) where T : class, new() { if (obj == null) { obj = new T(); } Type type = obj.GetType(); //得到類型的所有屬性,也就是表對應的實體模型的所有屬性 //嗮選一下只要公開的 PropertyInfo[] properts = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); if (properts.Any()) { foreach (PropertyInfo item in properts) { if (row.Table.Columns.IndexOf(item.Name) != -1) { if (row[item.Name] != null && row[item.Name] != DBNull.Value) { item.SetValue(obj, row[item.Name]); } } } } return obj; } }View Code
調用
static void Show() { DataTable data = new BDHelper().GetData("select * from Jack_News_TNews"); News news = new News(); var list = new TransitionDataTable().DataSetBindList(news, data); }