反射
放射是指在程序运行时动态的获取类的信息的机制,我们下面来看看C#中的反射。
Type
Type 为 System.Reflection 功能的根,也是访问元数据的主要方式。 使用 Type 的成员获取关于类型声明的信息,如构造函数、方法、字段、属性 (Property) 和类的事件,以及在其中部署该类的模块和程序集。
我们获取一个指定类型的Type有三种方法:
- 通过typeof直接获取;
- 通过调用GetType方法获取;
- 通过调用Type的静态方法GetType获取;
这三个方法都可以获取指定类型的Type对象,但是也有一点区别,具体可以参考下面两篇博客:
下面我们来看一个例子:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Type t1 = typeof(string);10 Console.WriteLine(t1.FullName);11 //System.String12 13 Type t2 = "hello type!".GetType();14 Console.WriteLine(t2.FullName);15 //System.String16 17 Type t3 = Type.GetType("System.String", false);18 Console.WriteLine(t3.FullName);19 //System.String20 21 Console.Read();22 }23 }24 }
获取类的信息
我们可以通过Type类型获取到类的所有信息,比如我们要获取类的所有方法信息的话,可以使用下面的代码:
1 using System; 2 using System.Reflection; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 {10 string str = "Hello Type!";11 12 Type t = str.GetType();13 //获取所有方法信息14 MethodInfo[] methodInfos = t.GetMethods();15 for (int i = 0; i < methodInfos.Length; i++)16 {17 Console.WriteLine(methodInfos[i].Name);18 }19 //仅获取非静态的公共方法信息20 methodInfos = t.GetMethods(BindingFlags.Instance | BindingFlags.Public);21 for (int i = 0; i < methodInfos.Length; i++)22 {23 Console.WriteLine(methodInfos[i].Name);24 }25 26 Console.Read();27 }28 }29 }
更多信息的获取方法可以参考帮助文档()。
调用指定的方法
下面我们看看如何获取一个类的指定方法并进行调用:
1 using System; 2 using System.Reflection; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 {10 string str = "Hello Type!";11 12 Type t = str.GetType();13 //对于存在多个重载的方法需要指明参数的类型14 MethodInfo method = t.GetMethod("Split", new []{ typeof(char[])});15 //调用方法16 string[] strs = method.Invoke(str, new object[] { new[] { ' '}}) as string[];17 for (int i = 0; i < strs.Length; i++)18 {19 Console.WriteLine(strs[i]);20 }21 22 Console.Read();23 }24 }25 }
Assembly
程序集可以看做一个或多个DLL或EXE文件的集合,可以通过程序集将重复的代码提取出来,可以重复使用。
我们首先创建一个类库项目,代码如下:
1 namespace StudyLib 2 { 3 public class MyClass 4 { 5 public int Add(int a, int b) 6 { 7 return a + b; 8 } 9 10 public int Add(int a, int b, int c)11 {12 return a + b + c;13 }14 }15 }
然后点击菜单栏-》生成-》生成XXX,可以获得对应的DLL文件,接下来我们使用Assembly读取DLL并执行其中的方法:
1 using System; 2 using System.Reflection; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 {10 Assembly assembly = Assembly.LoadFrom("E:\\study\\C#\\StudyLib\\StudyLib\\bin\\Debug\\StudyLib.dll");11 12 //输出所有类型名称13 Type[] types = assembly.GetTypes();14 for (int i = 0; i < types.Length; i++)15 {16 Console.WriteLine(types[i].FullName);17 }18 //StudyLib.MyClass19 20 //动态创建类并调用其中的方法21 Type t = assembly.GetType("StudyLib.MyClass");22 ConstructorInfo constructor = t.GetConstructor(Type.EmptyTypes);23 Object myClass = constructor.Invoke(new object[]{});24 25 MethodInfo method1 = t.GetMethod("Add", new[] { typeof (int), typeof (int)});26 int result1 = (int)method1.Invoke(myClass, new object[] { 100, 123});27 Console.WriteLine("第一个方法返回: " + result1);28 //第一个方法返回: 22329 30 MethodInfo method2 = t.GetMethod("Add", new[] { typeof(int), typeof(int), typeof(int)});31 int result2 = (int)method2.Invoke(myClass, new object[] { 100, 123, 456 });32 Console.WriteLine("第二个方法返回: " + result2);33 //第二个方法返回: 67934 35 Console.Read();36 }37 }38 }