说起反射,我觉得就是窥探一个程序集内部的实现,基本上就是这个意思。
并且反射无处不在,我们天天在使用,VS的智能提示就是通过反射获取到类的属性、方法等,还有反编译工具。
反射就是动态获取程序集的元数据的来操作类型的,
下面演示一下反射中得一些基本方法:
首先建一个类库,写一些普通类、接口、抽象类、属性、方法等
然后生成一下,将源文件中得dll拷贝到C盘下,这里这个dll文件就是程序集
在主函数中调用:
#region 加载指定的程序集,并且获取程序集中得所有类型 // //写一个类,里面写一些类型,把生成的dll放到磁盘中 // //加载ClassLibrary1.dll这个程序集,现在asm就是这个程序集 // Assembly asm = Assembly.LoadFile(@"C:ClassLibrary1.dll"); // //获取这个程序集中得类型名称(类名、枚举、接口、委托) // //这样搞会获取所有的(公有的私有的),那么面向对象那一套就不管用了 ////Type[] getNames= asm.GetTypes(); //Type[] getNames = asm.GetExportedTypes();//这种酒只能获取public了,别的都获取不到了 //foreach (Type item in getNames) //{ // Console.WriteLine(item.Name); //} #endregion
#region 加载程序集,获取Class1类下的所有方法 //获取程序集 Assembly asm = Assembly.LoadFile(@"C:ClassLibrary1.dll"); ////获取Class1这个类型,getClass1就表示Class1这个类型的元数据,它里面存了Class1的所有信息 Type getClass1 = asm.GetType("ClassLibrary1.Class1"); #region 获取所有非protected和非private方法 ////获取Class1中得所有方法 //MethodInfo[] getMathes = getClass1.GetMethods(); ////遍历所有的方法 //foreach (var item in getMathes) //{ // Console.WriteLine(item.Name);//会把所有的方法都打印出来包括ToString()啊Equals啊GetHashCode什么的 //} #endregion #region 获取里面的方法,Class1里面有个SayHi方法 MethodInfo method = getClass1.GetMethod("SayHi"); //打印出方法名 Console.WriteLine(method.Name); //创建一个类的对象,调用该方法 object obj = Activator.CreateInstance(getClass1); //调用该方法 method.Invoke(obj, null);//由于SayHi方法没有参数,这里Invoke方法的第二个参数就写null #endregion #endregion
我们可以看到,反射中有很多地方会用到Type,它实现反射的一个重要的类,通过它我们可以获取类中的所有信息包括方法、属性等。可以动态调用类的属性、方法。它其实就是对类的描述,
//加载程序集 Assembly asm = Assembly.LoadFile(@"C:ClassLibrary1.dll"); //获取Chinese类型的Type Type typeChinese = asm.GetType("ClassLibrary1.Chinese"); //获取person类的Type Type typePerson = asm.GetType("ClassLibrary1.Person"); //获取IJieKou接口的Type Type typeIJieKou = asm.GetType("ClassLibrary1.IJieKou"); //获取CouXiang抽象类的Type Type typeCouXiang = asm.GetType("ClassLibrary1.CouXiang"); //获取JinTai静态类的Type Type typeJinTai = asm.GetType("ClassLibrary1.JinTai");
1 #region IsAssignableFrom方法 2 //验证一下person类是不是chinese类的父类。在这里就是看能不能把chinese类赋值给person类 3 bool b = typePerson.IsAssignableFrom(typeChinese); 4 Console.WriteLine(b);//返回true,因为person类是chinese的父类 5 6 //看一下接口行不行 7 bool b1 = typeIJieKou.IsAssignableFrom(typeChinese); 8 Console.WriteLine(b1);//也是true, 9 #endregion
1 #region IsInstanceOfType方法 2 Object obj = Activator.CreateInstance(typeChinese); 3 //验证一下obj是不是Chinese类型的对象 4 bool b2 = typeChinese.IsInstanceOfType(obj); 5 Console.WriteLine(b2);//true 6 7 bool b3 = typePerson.IsInstanceOfType(obj); 8 Console.WriteLine(b3);//true 9 #endregion
1 #region IsSubclassOf方法 2 //验证Chinese是否是Person类的子类 3 bool b4 = typeChinese.IsSubclassOf(typePerson); 4 Console.WriteLine(b4);//true 5 6 //验证chinese是否是IJieKou的子类 7 bool b5 = typeChinese.IsSubclassOf(typeIJieKou); 8 Console.WriteLine(b5);//返回false,因为接口只有实不实现,不存在子父类关系 9 #endregion
1 #region IsAbstract,判断某个类型是否是一个抽象的。 2 Console.WriteLine(typeChinese.IsAbstract);//false 3 Console.WriteLine(typePerson.IsAbstract);//false 4 //接口、抽象类、静态类都不能被实例化,所以这里被认为是“抽象的” 5 Console.WriteLine(typeIJieKou.IsAbstract);//true 6 Console.WriteLine(typeJinTai.IsAbstract);//true 7 8 #endregion
通过反射获取类中得私有方法:
首先写一个类,这里我就简单写一个方法:
1 public class Person 2 { 3 private void Say() 4 { 5 Console.WriteLine("我是私有的。。"); 6 } 7 8 }
在主函数中通过反射去调用这个方法:
1 static void Main(string[] args) 2 { 3 Type type=typeof(Person); 4 MethodInfo method = type.GetMethod("Say", BindingFlags.NonPublic | BindingFlags.Instance); 5 object obj = Activator.CreateInstance(type); 6 method.Invoke(obj,null); 7 Console.ReadLine(); 8 }