上图是反射的基本流程
下面是一些反射的用法
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Reflection; 8 using System.Text; 9 using System.Threading.Tasks; 10 using System.Windows.Forms; 11 12 namespace 反射 13 { 14 public partial class Form1 : Form 15 { 16 public Form1() 17 { 18 InitializeComponent(); 19 } 20 21 class MyClass 22 { 23 public string m; 24 public void test() { } 25 public int MyProperty { get; set; } 26 } 27 //反射获取 MyClass 28 Type type = typeof(MyClass); 29 //获取类型名 30 private void button1_Click(object sender, EventArgs e) 31 { 32 textBox1.Text = type.Name; 33 } 34 //获取类全名 35 private void button2_Click(object sender, EventArgs e) 36 { 37 textBox1.Text = type.FullName; 38 } 39 //获取命名空间 40 private void button4_Click(object sender, EventArgs e) 41 { 42 textBox1.Text = type.Namespace; 43 } 44 //获取程序集名 45 private void button3_Click(object sender, EventArgs e) 46 { 47 textBox1.Text = type.Assembly.ToString(); 48 } 49 //获取模块名 50 private void button5_Click(object sender, EventArgs e) 51 { 52 textBox1.Text = type.Module.ToString(); 53 } 54 //获取基类名 55 private void button6_Click(object sender, EventArgs e) 56 { 57 textBox1.Text = type.BaseType.ToString(); 58 } 59 //判断是否是类 60 private void button7_Click(object sender, EventArgs e) 61 { 62 textBox1.Text = type.IsClass.ToString(); 63 } 64 //获取类的公共成员 65 private void button8_Click(object sender, EventArgs e) 66 { 67 MemberInfo[] arrs = type.GetMembers(); 68 foreach (var item in arrs) 69 { 70 string txt = $"{item.MemberType},{item} "; 71 textBox1.Text = Text; 72 73 } 74 } 75 76 77 //获取当前执行代码的程序集 78 Assembly assembly = Assembly.GetExecutingAssembly(); 79 80 //获取程序集全名 81 private void button9_Click(object sender, EventArgs e) 82 { 83 textBox1.Text = assembly.FullName; 84 } 85 //获取程序集的版本 86 private void button10_Click(object sender, EventArgs e) 87 { 88 textBox1.Text = assembly.GetName().Version.ToString(); 89 } 90 //获取程序集的初始位置 91 private void button11_Click(object sender, EventArgs e) 92 { 93 textBox1.Text = assembly.CodeBase; 94 } 95 //获取程序集的位置 96 private void button12_Click(object sender, EventArgs e) 97 { 98 textBox1.Text = assembly.Location; 99 } 100 //程序集的入口 101 private void button13_Click(object sender, EventArgs e) 102 { 103 textBox1.Text = assembly.EntryPoint.ToString(); 104 } 105 //获取程序集下包含的类型 106 private void button14_Click(object sender, EventArgs e) 107 { 108 Type[] types = assembly.GetTypes(); 109 string lx = ""; 110 foreach (var item in types) 111 { 112 lx += item.Name+" "; 113 } 114 textBox1.Text = lx; 115 } 116 } 117 }
反射定义 : 审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。
System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码
System.Reflection.Assembly
System.Reflection.MemberInfo
System.Reflection.EventInfo
System.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection.ConstructorInfo
System.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Type
反射:什么是反射?反射就是在程序运行的过程中,动态的获取类的成员,并对他们进行操作。包括动态调用方法,动态获取,设置属性等。通过特性,也能是想IOC,AOP等功能
特性:特性只有在使用反射的时候才能发挥它最大的作用,通过反射获取到自定义的特性,再根据特性进行操作,例如在通过反射实现ORM的时候,如果一个熟悉设置了不需要ORM的特性,则可以忽略该属性。如果没有反射,那么可以把特性当做注释,它不会对代码的运行造成任何影响。但它和注释的区别在于,它会被编译进程序集,这样才能通过反射获取到这些特性
反射常用的类有Assembly,Activator,Type这几个类
Assembly获取程序集应用,可以通过Load,LoadFile,LoadFrom这几个方法将dll文件加载进当前程序集。如果需要反射的类位于当前程序集,则可以不使用此类
Activator用于动态的创建一个类的实例,通过Assembly加载的程序集,可以获取到它内部的所有的Type,而Activator.Crea teInstance方法可以为当前对象创建一个实例。(Assembly也有CreateInstance方法用于创建类的实例)。
Type表示一个类型,也可以通过typeof获取例如typeof(int)得到的就是int类型,然后Type对象有很多的方法可以获取对象的成员,包括字段,方法,属性等等对象内部的所有都可以通过Type获得
反射被广泛地用于那些需要在运行时检测或修改程序行为的程序中。这是一个相对高级的特性,只有那些语言基础非常扎实的开发者才应该使用它。如果能把这句警示时刻放在心里,那么反射机制就会成为一项强大的技术,可以让应用程序做一些几乎不可能做到的事情。
优点:
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类;
缺点:
1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
2、使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。 至于执行效率的话,还可以,因为它是一种强类型语言,执行效率不错。不过,建议将反射过后,保存进 cache中。
尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心:
首先是性能:
反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程序中使用反射。
安全:
使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。
成员的内部暴露:
由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化