1.前言
以前也写过几篇关于反射的博客(简单反射机制),但都理解的不是很深刻,现在在做项目中又一次的用到了反射,在此再总结一下,对于反射的理解。
2.什么是反射?
最近看博客,才理解了反射无处不在,我们经常用到的VS中的智能提示,就是通过反射获取到类的属性,方法等。反射就是动态获取程序集中的元数据来操作类型的。说的通俗一点,反射就是直接调用Bin文件夹下的.dll来创建对象,调用成员,摆脱了以前通过实例化也就是New操作的方法来调用对象的方法。
小结:反射就是直接调用.dll来创建对象,反射让创建对象的方式发生了变化。
3.什么是程序集(Assembly)
程序集是.net中的概念,比如.net中的.exe或者.dll文件都是程序集。可以把其看做是一堆相关的类的打包。比如包含一些资源文件、类型元数据等
其中调用Assembly(程序集)的GetTypes()方法可以得到程序集中定义的所有的类型
调用Assembly的GetType(name)方法可以得到Assembly中定义的全名为name的类型信息
3.Type类介绍
Type类是实现反射的一个重要的类,通过它可以获取类中所有的信息包括方法、属性等,通过它可以设置属性或者调用方法。
4.重要的类
Assembly:表示一个程序集,它是一个可重用、可自我描述的公共语言运行时应用程序构造块。
Type:表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
MethodInfo:发现方法的属性并提供对方法元数据的访问。
PropertyInfo:发现属性 (Property) 的属性 (Attribute) 并提供对属性 (Property) 元数据的访问。
看了上图,就明白了反射其实就是另外一种机制,另外一种直接通过.dll文件来动态的创建类的对象。
5.Demo
以下是关于这方面知识,自己联系的Demo
<span style="font-size:18px;">using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ClassLibrary1.dll"); //动态加载一个程序集 //C:\Users\ZHOU\Desktop\lianxi\ConsoleApplication2\bin\Debug Assembly ass = Assembly.LoadFile("C:/Users/ZHOU/Desktop/lianxi/ConsoleApplication2/bin/Debug/ClassLibrary1.dll"); //获取程序集中公共的类型,通常指的是public的类 Type[] types = ass.GetExportedTypes(); foreach (Type type in types) { //类的名字 Console.WriteLine(type.Name); //类的全名称(命名空间.类名) Console.WriteLine(type.FullName); } //可以获取到所有的类,包括的是私有的类 //Type[] typ= ass.GetTypes(); foreach (Type item in types) { Console.WriteLine(item.Name); } Console.Read(); //使用FileCommon的默认构造函数创建对象 object o = ass.CreateInstance("commom.FileCommon"); Type t = o.GetType(); //使用指定参数的构造函数创建对象 object oo = Activator.CreateInstance(t, "zs", 18); //判断student类型的对象,是否可以赋给person。类型的引用调换 bool r = typeof(Person).IsAssignableFrom(typeof(Student)); //判断学生对象是不是某个类的实例 Student b=new Student(); Type d=typeof(Student); bool f=d.IsInstanceOfType(b); //判断是不是某个类的子类 bool z = typeof(Person).IsSubclassOf(typeof(Student)); #region 动态获取程序集中的属性 //GetProperties获取类型中的所有属性 PropertyInfo[] pis = d.GetProperties(); foreach (PropertyInfo pi in pis) { if (pi.Name == "Name") { //动态给属性赋值 pi.SetValue(b, "jk", null); pi.GetValue(b); } } #endregion //Type :描述类型的 //methodInfo:描述方法 #region 动态获取方法 MethodInfo[] mis = d.GetMethods(); foreach (MethodInfo mi in mis) { //获取子类中的扩展方法 if (mi.IsSpecialName) { } } #endregion //动态调用Student类的SayHi方法 MethodInfo mid = d.GetMethod("Add"); mid.Invoke(d, null); //也可以通过获取的type类型直接调用 b.Add(); } } interface Person { int Add(); }; class Student : Person { public int Add() { throw new NotImplementedException(); } } } </span>
总结:反射其实就是另外一种创建对象的机制,只不过更灵活而已,关于以上提到的几个类,MSDN上有详细的解释,里面有很多可以用到的方法,想学习的可以查一下。