20181114_反射_泛型反射
阿新 • • 發佈:2018-11-14
反射的核心: 動態; 利用反射, 一切都可以動態實現
一. 以下程式碼用到的People和PeopleDTO類程式碼:
/// <summary> /// 基於資料庫查詢得到這樣一個類; 和資料庫對應 /// </summary> public class People { public People() { Console.WriteLine("{0}被建立", this.GetType().FullName); } public int Id { get; set; } public string Name { get; set; } public string Description; } /// <summary> /// 對應著介面繫結; 和程式對應 /// </summary> public class PeopleDTO { public PeopleDTO() { Console.WriteLine("{0}被建立", this.GetType().FullName); } public int Id { get; set; } public string Name { get; set; }//ShortName 特性 public string Description; }
二. 對已知型別的簡單反射
People people = new People(); people.Id = 123; people.Name = "wukong"; people.Description = "大師兄"; { //對已知型別的簡單反射 注意: 反射的寫法有很多種,前面使用程式集的字元, 這裡直接使用People, 都是為了獲取型別, 反射最主要的問題就是拿到型別, 而不用管通過什麼方法拿到 Type type = typeof(People); object oPeople = Activator.CreateInstance(type); //建立一個預設物件 foreach (var item in type.GetProperties()) //type.GetProperties()表示 獲取屬性資訊 { // type.GetFields() 表示獲取欄位資訊 //在C#中規定, 有get; set; 的是屬性; 沒有get;set;的是欄位 Console.WriteLine(type.Name); Console.WriteLine(item.Name); //每一個屬性的名稱 Console.WriteLine(item.GetValue(oPeople ));//獲取屬性的值 if (item.Name.Equals("Id")) { item.SetValue(oPeople, 223); } else if (item.Name.Equals("Name")) { item.SetValue(oPeople, "八戒"); } }
三. 基於泛型的反射
a) 泛型類程式碼:
public class GenericClass<T, W, X> { public void Show(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } }
b) 使用反射建立一個泛型類的例項程式碼:
//對於泛型的反射; 其中GenericClass `3 ; 因為泛型編譯之後就會生成一個這樣的類; `表示佔位符; 3表示GenericClass有3個型別的引數; 如果有兩個, 那麼這裡就是個2 Assembly assembly = Assembly.Load("MyDB.SqlServer"); Type type = assembly.GetType("MyDB.SqlServer.GenericClass`3"); //這種方式無法建立改物件的例項的; 因為沒有為泛型指定例項化物件 //object oGeneric = Activator.CreateInstance(type); //為泛型指定型別進行例項化 Type newType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) }); //使用newType建立泛型的型別 object oGeneric = Activator.CreateInstance(newType);
四. 使用反射呼叫泛型類的泛型方法
a) GenericDouble類程式碼:
public class GenericDouble<T> { public void Show<W, X>(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } }
b) 反射呼叫泛型類的泛型方法
Type typeGenericDouble = assembly1.GetType("MyDB.SqlServer.GenericDouble`1"); // 將類的泛型規定為int型別; 因為它是泛型的, 使用(例項化)之前必須要指定泛型的型別 //使用反射時, 則需要使用typeof(int)將泛型的T指定為想要建立的型別. 這裡指定為int型別 Type newType = typeGenericDouble.MakeGenericType(new Type[] { typeof(int) }); //建立物件, object oGeneric = Activator.CreateInstance(newType); //找物件裡面的方法 MethodInfo method = newType.GetMethod("Show"); //method.IsGenericMethod //判斷此方法是不是一個泛型方法 //MakeGenericMethod 指定方法的型別 MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) }); //傳遞的引數型別, 必須和上面的引數型別保持一致 methodNew.Invoke(oGeneric, new object[] { 123, "沙和尚", DateTime.Now });
五. 基於反射, 利用泛型實現DTO
a) 將People轉成PeopleDTO; 普通硬編碼, 死編碼
People people = new People(); people.Id = 123; people.Name = "wukong"; people.Description = "大師兄"; PeopleDTO peopleDTO = new PeopleDTO() { Id = people.Id, Name = people.Name, Description = people.Description };//硬編碼轉換 效率最高
b) 利用反射實現
Type typePeople = typeof(People); Type typePeopleDTO = typeof(PeopleDTO); object peopleDTO = Activator.CreateInstance(typePeopleDTO); foreach (var prop in typePeopleDTO.GetProperties()) //訪問所有屬性 { #region 使用屬性名稱字串來判斷; 低階方法 //if (prop.Name.Equals("Id")) //{ // //object value = typePeople.GetProperty("Id").GetValue(people); // object value1 = typePeople.GetProperty(prop.Name).GetValue(people); // prop.SetValue(peopleDTO, value1); //} //else if (prop.Name.Equals("Name")) //{ // //object value = typePeople.GetProperty("Name").GetValue(people); // object value1 = typePeople.GetProperty(prop.Name).GetValue(people); // prop.SetValue(peopleDTO, value1); //} #endregion //如果兩個類的欄位名稱都一樣, 則可以使用下面的方法; 如果兩個類的欄位不一樣, 則需要使用特性 object value = typePeople.GetProperty(prop.Name).GetValue(people); prop.SetValue(peopleDTO, value); } //訪問欄位 foreach (var filed in typePeopleDTO.GetFields()) { object value = typePeople.GetField(filed.Name).GetValue(people); filed.SetValue(peopleDTO, value); }