1、为何要使用反射编程
程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。您可使用反射动态地建立类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。而后,能够调用类型的方法或访问其字段和属性。浏览器
2、反射机制的原理安全
审查元数据并收集关于它的类型信息的能力。框架
元数据是一种二进制信息,用以对存储在公共语言运行库可移植可执行文件 (PE) 文件或存储在内存中的程序进行描述。将您的代码编译为 PE 文件时,便会将元数据插入到该文件的一部分中。函数
元数据以非特定语言的方式描述在代码中定义的每一类型和成员。元数据存储如下信息: 测试
3、反射的做用spa
反射一般具备如下用途:.net
使用 Assembly 定义和加载程序集,加载在程序集清单中列出的模块,以及今后程序集中查找类型并建立该类型的实例。code
使用 Module 了解以下的相似信息:包含模块的程序集以及模块中的类等。您还能够获取在模块上定义的全部全局方法或其余特定的非全局方法。对象
使用 ConstructorInfo 了解如下信息:构造函数的名称、参数、访问修饰符(如public 或private)和实现详细信息(如 abstract 或virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。
使用 MethodInfo 了解如下信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法来调用特定的方法。
使用 FieldInfo 了解如下信息:字段的名称、访问修饰符(如 public 或private)和实现详细信息(如static)等;并获取或设置字段值。
使用 EventInfo 来了解以下的相似信息:事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。
使用 PropertyInfo 来了解以下的相似信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。
使用 ParameterInfo 来了解以下的相似信息:参数的名称、数据类型、参数是输入参数仍是输出参数,以及参数在方法签名中的位置等。
当您在一个应用程序域的仅反射上下文中工做时,请使用 CustomAttributeData 来了解有关自定义属性的信息。使用 CustomAttributeData,您没必要建立属性的实例就能够检查它们。
System.Reflection.Emit 命名空间的类提供了一种特殊形式的反射,使您可以在运行时构造类型。
反射也可用于建立称做类型浏览器的应用程序,它使用户可以选择类型,而后查看有关选定类型的信息。
反射还有其余一些用途。JScript 等语言编译器使用反射来构造符号表。System.Runtime.Serialization 命名空间中的类使用反射来访问数据并肯定要持久保存的字段。System.Runtime.Remoting 命名空间中的类经过序列化来间接地使用反射。
以上摘自http://msdn.microsoft.com/zh-cn/library/f7ykdhsy%28v=vs.80%29
4、一些小知识
一、类型(Type) 对象是什么
好比 object x; x是对象,object就是它的类型,在程序中如何描述类型这个概念呢?就是Type(System.Type)。要获取某个类的类型能够用typeof()操做符
object a;object b;
DataTable t;
Type aType = typeof(object);Type bType = typeof(object);tType = typeof(DataTable);
aType==bType!=tType;
二、程序集(Assembly)
就是你IDE生成的.exe或.dll文件的运行时就叫程序集。全部的代码都在程序集中。你能够经过Assembly.Load()系列函数动态加载程序集(这一步是动态+载代码的前提,由于全部的代码都在程序集中)。
三、动态加载
咱们普通调用代码是: 对象名.方法名(参数列表);
class a{
void func(int x){}
public static void Main(string[] args)
{
//建立对象
a a1 = new a();
//调用函数
a1.func(1);
}
}
用反射动态调用代码是
//加载程序集
System.Reflection.Assembly asm = Assembly.LoadFile(assemblyPath);
//获取类型
Type aType = asm.GetType( "名字空间.类名 ");
//获取没有参数的构造函数
System.Reflection.ConstructorInfo conn = t.GetConstructor(new Type[0]);
//调用没有参数的构造函数,Invoke返回object它其是a类
object a1 = conn.Invoke(new object[0]);
//获取参数类型为int,函数名为func的方法
MethodInfo method = t.GetMethod( "func ",new Type[]{typeof(int)});
//在a1上调用func方法,参数为1
method.Invoke(a1,new object[]{1});
动态调用(后一种方法)比静态调用更复杂,并且效率大概低20倍(网上有个哥们好像测试过)。只有在特殊的时候才调用动态加载动态调用---好比,你的主程序启动的时候子模块尚未,要根据登录信息下载子模块代码并调用子模块代码,就只能用动态+载来实现了.
四、元数据
.net生成的IL代码中标明了在这个(exe,dll)文件中全部的class(类) method(方法)Attribute(属性) Property(类属性)的签名和调用方法信息,这些信息就叫作元数据。所谓的Reflection反射,就是利用元数据,能够了解到某个assembly(基本等同文件)中的class。。。。。 (就是上面那一串咚咚)信息和调用方法。
五、.net framework
在.net framework中反射类基本都在System.Reflection中。System.Type是反射的核心类.
与它相关的还有System.Attribute命名空间。
5、实例
一、Assembly的使用
Assembly是一个包含来程序的名称,版本号,自我描述,文件关联关系和文件位置等信息的一个集合。在.net框架中经过Assembly类来支持,该类位于System.Reflection下,物理位置位于:mscorlib.dll。咱们能够经过Assembly的信息来获取程序的类,实例等编程须要用到的信息。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ConsoleApplication5 { class Program { static void Main(string[] args) { People people;//这种使用方式能够获取相应类中的变量、方法等元素 string assemblyName = @"ConsoleApplication5"; string strongClassName = @"ConsoleApplication5.Male";//能够把这里的声明看做是路径:命名空间下的类名 people = (People)Assembly.Load(assemblyName).CreateInstance(strongClassName);//这里也可使用Male或者Female变量来获取相应的属性及方法 Console.WriteLine(people.name); //Assembly ass = Assembly.Load(assemblyName);//这种使用方式能够获取程序的名称,版本号,自我描述,文件关联关系和文件位置等信息的一个集合 //Assembly ass1 = Assembly.LoadFrom(@"D:\work\myTest\myTest\bin\myTest.dll"); ////获取程序集显示名称 //Console.WriteLine(ass1.FullName); ////获取程序集中定义的类型 //Type[] types = ass.GetTypes(); //foreach (Type t in types) //{ // Console.WriteLine(t.FullName); //} Console.ReadKey(); } }
class People { public string name; } class Male : People { public Male() { name = "你好"; } public string sex = "男"; public string hello() { return "我是"+sex+"生"; } } class Female : People { public Female() { name = "Hello"; } public string sex = "女"; public string hello() { return "我是" + sex + "生"; } } }
二、Module的使用
三、ConstructorInfo 的使用
继续试用上面的例子
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ConsoleApplication5 { class Program { static void Main(string[] args) { Assembly ass = Assembly.Load("ConsoleApplication5"); Assembly ass1 = Assembly.LoadFrom(@"D:\work\myTest\myTest\bin\myTest.dll"); Type type = ass.GetType("ConsoleApplication5.People"); //将获得的类型传给一个新建的构造器类型变量 ConstructorInfo constructor = type.GetConstructor(new Type[0]); //使用构造器对象来建立对象 object obj = constructor.Invoke(new Object[0]); //输出对象类型 Console.WriteLine(obj); } } }
四、MethodInfo 的使用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace MethodInfoInvokeDemo { public class ReflectTest { public void MethodWithNoParaNoReturn() { Console.WriteLine("不带参数且不返回值的方法"); } public string MethodWithNoPara() { Console.WriteLine("不带参数且有返回值的方法"); return "MethodWithNoPara"; } public string Method1(string str) { Console.WriteLine("带参数且有返回值的方法"); return str; } public string Method2(string str, int index) { Console.WriteLine("带参数且有返回值的方法"); return str + index.ToString(); } public string Method3(string str, out string outStr) { outStr = "bbbb"; Console.WriteLine("带参数且有返回值的方法"); return str; } public static string StaticMethod() { Console.WriteLine("静态方法"); return "cccc"; } } class Program { static void Main(string[] args) { Type type = typeof(ReflectTest); object reflectTest = Activator.CreateInstance(type); //不带参数且不返回值的方法的调用 MethodInfo methodInfo = type.GetMethod("MethodWithNoParaNoReturn"); methodInfo.Invoke(reflectTest, null); Console.WriteLine(); //不带参数且有返回值的方法的调用 methodInfo = type.GetMethod("MethodWithNoPara"); Console.WriteLine(methodInfo.Invoke(reflectTest, null).ToString()); Console.WriteLine(); //带参数且有返回值的方法的调用 methodInfo = type.GetMethod("Method1", new Type[] { typeof(string) }); Console.WriteLine(methodInfo.Invoke(reflectTest, new object[] { "测试" }).ToString()); Console.WriteLine(); //带多个参数且有返回值的方法的调用 methodInfo = type.GetMethod("Method2", new Type[] { typeof(string), typeof(int) }); Console.WriteLine(methodInfo.Invoke(reflectTest, new object[] { "测试", 100 }).ToString()); //Console.WriteLine(); //methodInfo = type.GetMethod("Method3", new Type[] { typeof(string), typeof(string) }); //string outStr = ""; //Console.WriteLine(methodInfo.Invoke(reflectTest, new object[] { "测试", outStr }).ToString()); Console.WriteLine(); //静态方法的调用 methodInfo = type.GetMethod("StaticMethod"); Console.WriteLine(methodInfo.Invoke(null, null).ToString()); Console.ReadKey(); } } }