在上篇《程序集和反射(一)》中,我们重点讲解了“程序集”和反射的基本概念,原理等。有的读者可能会认为这些枯燥的理论没啥用,其实不然。据我的经历,面试中问到的很多。能够透彻的理解“程序集,反射等”,而且能在日常开发中灵活的运用反射,是一个优秀的.NET开发人员的重要参考标准。呵呵。
本节中,我将通过具体的实例。教大家如何在)C#).NET开发中使用反射。
首先,我新建一个普通的类库项目。在该项目的测试类中,定义好 属性、静态方法、实例方法、无参方法等... 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ReflectorTest { class Test { private string name; public string Name { get; set; } /// <summary> /// 静态方法 /// </summary> /// <returns></returns> public static string staticMethod(string name) { return name; } /// <summary> /// 实例方法 /// </summary> /// <param name="name"></param> /// <returns></returns> public string sayHello(string name) { return "hello:" + name; } /// <summary> /// 无参的方法 /// </summary> /// <returns></returns> public string noParm() { return "I'M A noParm Method"; } } }
上面的类库项目,编译通过后,会生成一个DLL文件。好的,我们就是要通过“反射”技术,来尝试着看看这个DLL里面包含的相关元素信息,做一些模拟的操作等。
有点类似于“反编译”吧?呵呵。其实著名的Reflector.NET反编译工具,就是利用反射的原理。还有Microsoft Visual Studio 中的调试,背后也是利用反射技术..
具体的使用代码如下(都有详细的使用说明,注释。读者可以一目了然):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace Demo { class Program { static void Main(string[] args) { // reflectorInfo(); reflectorDemo(); Console.ReadKey(); } /// <summary> /// 利用反射去调用程序集中(包含的类)所包含的方法,属性,成员... /// </summary> public static void reflectorDemo() { Assembly ass; Type type; MethodInfo method; try { ass = Assembly.LoadFile(@"F:\Projects\ReflectorTest\ReflectorTest\bin\Debug\ReflectorTest.DLL");//根据物理DLL路径尝试加载 type = ass.GetType("ReflectorTest.Test");//根据类型名称,反射出该类型(注意格式是:“命名空间.类名”) object o =Activator.CreateInstance(type);//创建该类型的对象实例 method=type.GetMethod("sayHello");//反射获取方法(实例方法) string s = (string)method.Invoke(o,new string[] {"dinglang"});//调用实例方法 Console.WriteLine("调用实例方法返回:"+s); method=type.GetMethod("noParm");//无参方法 s= (string) method.Invoke(o,null);//调用无参函数 Console.WriteLine("调用无参方法返回:"+s); //type.GetProperties()//获取该类型下面的所有公共属性 method=type.GetMethod("staticMethod");//静态函数 s=(string)method.Invoke(null,new string[]{"dinglang"});//调用静态方法 Console.WriteLine("调用静态方法返回:"+s); //根据指定的属性名称,获得属性值 type.GetProperty("Name").GetValue(o,null); //给属性设值 type.GetProperty("Name").SetValue(o, "dinglang", null); } catch (Exception) { throw; } finally { ass=null; type=null; method=null; } } /// <summary> /// 利用反射获取程序集中类,类的成员(方法,属性等) /// </summary> public static void reflectorInfo() { Assembly ass = Assembly.LoadFrom(@"F:\Projects\ReflectorTest\ReflectorTest\bin\Debug\ReflectorTest.DLL");//加载程序集 Module[] modules = ass.GetModules();//模块信息 Type[] types = ass.GetTypes();//获取该程序集所包含的所有类型 foreach (var item in types) { Console.WriteLine("所包含的类型类型名称:" + item.Name); MethodInfo[] methods = item.GetMethods();//获取该类型下所包含的方法信息 foreach (var method in methods) { Console.WriteLine("该类下所包含的方法名称:"+method.Name); } PropertyInfo[] PropertyInfo = item.GetProperties(); foreach (var pro in PropertyInfo) { Console.WriteLine("该类下所包含的属性名称:" + pro.Name); } } } } }读者可以参照以上代码,自己实际动手敲代码试试。还不夸张的说,当你真正学会了“反射”后,你会爱上“反射”。但是值得提醒的是:反射可能会很耗性能哦。希望大家在适当的场合下合理使用。