反射的核心: 动态; 利用反射, 一切都可以动态实现
一. 以下代码用到的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); }