在很多項目的很多地方都發現了一個共同的術語 反射 有時候我在想這是個什麼東西,能幹啥。 這幾天靜下心來,好好地去翻了翻書,看了看別人的博客。 也自己比著寫了兩個泛型反射方法。還算理解了一小部分,寫個記錄。 上例子代碼: 這是通過反射工廠來創建實例: 這是將Datatable里的數據反射到LIst集合 ...
在很多項目的很多地方都發現了一個共同的術語---反射
有時候我在想這是個什麼東西,能幹啥。
這幾天靜下心來,好好地去翻了翻書,看了看別人的博客。
也自己比著寫了兩個泛型反射方法。還算理解了一小部分,寫個記錄。
上例子代碼:
這是通過反射工廠來創建實例:
public static T TFactory<T>() where T : class { Type ty = typeof(T); string spaceStr = ty.Namespace; string fullStr = ty.FullName; Assembly ass = Assembly.Load(spaceStr); object ob = ass.CreateInstance(fullStr, true); return (T)ob; }
這是將Datatable里的數據反射到LIst集合中:
public static List<T> ToList<T>(this DataTable dt) { if (dt == null || dt.Rows.Count == 0) { return default(List<T>); } List<T> list = new List<T>(); Type type = typeof(T); PropertyInfo[] per = type.GetProperties(); foreach (DataRow row in dt.Rows) { T entity = Activator.CreateInstance<T>(); foreach (PropertyInfo p in per) { object obj = Convert.ChangeType(row[p.Name], p.PropertyType); p.SetValue(entity, obj); } list.Add(entity); } return list; }
猛地一看是不是有點哇塞~,很酷的感覺。
來看看這個反射是個什麼東西吧,按照我的理解+書上的指引來大體粗略的寫一下反射
反射
大多數程式都要處理數據,包括度,寫,操作和顯式數據。
然而,對於某些程式來說,他們操作的不是數字,文本或圖形,而是程式和程式類型本身的信息。
有關程式及其類型的數據被稱為元數據(matadata),他們保存在程式的程式集中(.dll)。
程式在運行時,可以查看其它程式及或其本身的元數據。一個運行的程式查看本身的元數據或其它程式的元數據的行為叫做"反射"。
反射命名空間:System.Reflection
Type類
BCL(基類庫)聲明瞭一個叫做Type的抽象類,他被設計用來包含類型的特性。使用這個類能讓我們獲取程式使用的類型的信息。
由於Type是抽象類,因此他不能有實例。而是在運行時,CLR(公共語言運行庫)從Type(RunTimeType)派生的類的實例,Type包含了類型的信息。
當我們要訪問這些實例時,CLR不會返回派生類的引用而是Type基類的引用,
需要瞭解的Type重要事項:
1.對於程式中用到的每一個類型,CLR都會創建一個包含這個類型的Type類型的對象。
2.程式中用到的每一個類型都會關聯到獨立的Type類的對象。
3.不管創建的類有多少個實例,只有一個Type對象會關聯到所有的這些實例。
如圖:一個運行的程式,他有兩個MyClass對象和一個OtherClass對象。註意:儘管有兩個MyClass的實例,只會有一個Type對象來表示他。
我們可以從Type對象中獲取需要瞭解的有關類型的幾乎所有信息。
列一下常用的成員吧。
System.Type類部分的成員。
獲取Type對象
object類包含了一個叫做GetType的方法,他返回對實例的Type對象的引用。
由於每一個類型最終都是從object繼承的,所以我麽可以在任何類型對象上使用GetType方法來獲取他的Type對象。
Type type = "任何對象".GetType();
下麵演示一下一個基類跟派生子類。在foreach迴圈中輸出類的名字以及公用欄位的名字。
基類與派生類:
class BaseClass //基類 { public int BaseField = 0; } class DerivedClass : BaseClass //派生類 { public int DerivedField = 0; }
通過反射輸出類信息:
BaseClass bc = new BaseClass(); //基類 DerivedClass dc = new DerivedClass();//派生類 BaseClass[] bca = new BaseClass[] { bc, dc }; foreach (var v in bca) { Type type = v.GetType(); Console.WriteLine("Type:{0}",type.Name);//輸出類名稱 FieldInfo[] fields = type.GetFields();//獲取所有公用欄位 foreach (var f in fields) Console.WriteLine("Field:{0}",f.Name);//輸出公用欄位名稱 }
輸出結果為:
類名與公用屬性全部被輸出了。
我們還可以通過typeof運算符來獲取Type對象。
只需提供類型名作為操作數,他就會返回Type對象的引用(通常都會用在泛型方法中),如代碼所示。
Type type = typeof(BaseClass);
總結
反射我只是初窺門徑,如果有錯誤的地方請各位大佬指正。
反射肯定不會只輸出這些名字。
反射還可以設置類型里公用的值。還可以調用類型中公用的方法。
等到下一篇講吧。