反射是指对一个程序集中的元数据进行检查的过程。说明白一点,就是可以访问和使用一个dll里面所有的东西,并且是运行动态时的调用,而不是普通编译时的绑定,这样使程序更加的自由和灵活,但是性能较低。
反射一般可以用于:插件的开发、特性和程序的动态调用等等。
1.建立2个项目,第一个输出类库,第二个输出控制台程序,然后使用反射的方式调用
2.第一个类库的dll是
代码
- using System;
-
- namespace ClassLibrary1
- {
- public class Class1
- {
- public Class1()
- {
- Console.WriteLine("无参构造");
- }
- public Class1(string a)
- {
- Console.WriteLine("有参构造");
- }
- public string A(int a, int b)
- {
- return "有参数有返回值:" + a + b;
- }
-
- public void B(int a, int b)
- {
- Console.WriteLine("有参数无返回值:" + a + b);
- }
- public void C()
- {
- Console.WriteLine("无参无返回值");
- }
- }
- }
3. 第二个项目使用反射调用
这里我们用了4种方法,分别是:
a.调用构造参数
b.调用有参数有返回值
c.调用有参数无返回值
d.调用无参无返回值
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
-
- namespace ConsoleApp4
- {
- static class Program
- {
- static void Main(string[] args)
- {
-
- Assembly assembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + @"a\ClassLibrary1.dll"); //获取整个dll文件
- Type type = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- ConstructorInfo info2 = type.GetConstructor(new Type[] { typeof(string) });
- info2.Invoke(new object[] { "asd" }); //执行有参构造函数
- Console.WriteLine("####################");
-
- Type type1 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- MethodInfo mi1 = type1.GetMethod("A"); //调用方法A
- Object obj1 = Activator.CreateInstance(type1); //快速实例化,相当于new
- object[] objParams1 = new object[] { 1, 2 }; //方法的参数
- Object returnValue = mi1.Invoke(obj1, objParams1); //接收参数
- Console.WriteLine(returnValue);
- Console.WriteLine("####################");
-
- Type type2 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- MethodInfo mi2 = type2.GetMethod("B"); //调用方法B
- Object obj2 = Activator.CreateInstance(type2); //快速实例化,相当于new
- object[] objParams2 = new object[] { 1, 2 }; //方法的参数
- mi2.Invoke(obj2, objParams2); //执行
- Console.WriteLine("####################");
-
- Type type3 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- MethodInfo mi3 = type3.GetMethod("C"); //调用方法C
- Object obj3 = Activator.CreateInstance(type3); //快速实例化,相当于new
- mi3.Invoke(obj3, null); //执行
-
- Console.ReadKey();
- }
- }
- }
4.效果
拓展
其实上面的方法也可以是InvokeMember方法完成。
1.代码
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
-
- namespace ConsoleApp4
- {
- static class Program
- {
- static void Main(string[] args)
- {
-
- Assembly assembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + @"a\ClassLibrary1.dll"); //获取整个dll文件
- //Type type = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- //ConstructorInfo info2 = type.GetConstructor(new Type[] { typeof(string) });
- //info2.Invoke(new object[] { "asd" }); //执行有参构造函数
- //Console.WriteLine("####################");
-
- //Type type1 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- //MethodInfo mi1 = type1.GetMethod("A"); //调用方法A
- //Object obj1 = Activator.CreateInstance(type1); //快速实例化,相当于new
- //object[] objParams1 = new object[] { 1, 2 }; //方法的参数
- //Object returnValue = mi1.Invoke(obj1, objParams1); //接收参数
- //Console.WriteLine(returnValue);
- //Console.WriteLine("####################");
-
- //Type type2 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- //MethodInfo mi2 = type2.GetMethod("B"); //调用方法B
- //Object obj2 = Activator.CreateInstance(type2); //快速实例化,相当于new
- //object[] objParams2 = new object[] { 1, 2 }; //方法的参数
- //mi2.Invoke(obj2, objParams2); //执行
- //Console.WriteLine("####################");
-
- //Type type3 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- //MethodInfo mi3 = type3.GetMethod("C"); //调用方法C
- //Object obj3 = Activator.CreateInstance(type3); //快速实例化,相当于new
- //mi3.Invoke(obj3, null); //执行
-
-
-
-
- Type type4 = assembly.GetType("ClassLibrary1.Class1"); //获取dll中的类型,参数是命名空间.类名
- object obj4 = Activator.CreateInstance(type4);
- //BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static 静态的时候需要加
-
- Object returnValue4 = type4.InvokeMember("A", BindingFlags.InvokeMethod, null, obj4, new object[] { 1, 2 });
- Console.WriteLine(returnValue4);
-
- type4.InvokeMember("B", BindingFlags.InvokeMethod,null, obj4, new object[] { 1, 2 });
-
- type4.InvokeMember("C", BindingFlags.InvokeMethod ,null, obj4, null);
-
-
-
-
- Console.ReadKey();
- }
- }
- }
2.效果是一样的
其中Assembly.LoadFile和Assembly.LoadFrom是有区别的。
Assembly.LoadFile,只加载自己,不加载依赖项,意思就是除过自己,不加载关联的dll。
Assembly.LoadFrom,不仅加载自己,还加载依赖项,除过自己,还加载自己关联其他的dll。
大部分的内容都在type点里面,里面包含了所有的对象,比如字段,属性,方法等等