反射提供了封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性

使用场景

  • 需要访问程序元数据的特性
  • 检查和实例化程序集中的类型
  • 在运行时构建新类型。使用 System.Reflection.Emit 中的类
  • 执行后期绑定,访问在运行时创建的类型的方法

    反射用途

    | 类型 | 作用 | | —- | :—- | | Assembly | 定义和加载程序集,加载程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例 | | Module | 了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法 | | ConstructorInfo | 了解构造器的名称、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数 | | MethodInfo | 了解方法的名称、返回类型、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法 | | FieldInfo | 了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值 | | EventInfo | 了解事件的名称、事件处理程序数据类型、自定义特性、声明类型和反射类型等,并添加或移除事件处理程序 | | PropertyInfo | 了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,并获取或设置属性值 | | ParameterInfo | 了解参数的名称、数据类型、参数是输入参数还是输出参数等,以及参数在方法签名中的位置等 |

反射用到的命名空间

  • System.Reflection
  • System.Type
  • System.Reflection.Assembly

    反射用到的主要类

  • System.Type :通过这个类可以访问任何给定数据类型的信息

  • System.Reflection.Assembly: 可以用于访问给定程序集的信息,或者把这个程序集加载到程序中

    System.Type

    一个抽象的基类。Type 有与每种数据类型对应的派生类,使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。

获取给定类型Type值

typeof 运算符

  1. Type t = typeof(string);

对象的GetType()方法

  1. string s = "guo";
  2. Type t = s.GetType();

Type类的静态方法GetType()

  1. Type t = Type.GetType("System.String");

Type 属性

属性 描述
Name 数据类型名
FullName 数据类型的完全限定名(包括命名空间名)
Namespace 定义数据类型的命名空间名
IsAbstract 指示该类型是否是抽象类型
IsArray 指示该类型是否是数组
IsClass 指示该类型是否是类
IsEnum 指示该类型是否是枚举
IsInterface 指示该类型是否是接口
IsPublic 指示该类型是否是公有的
IsSealed 指示该类型是否是密封类
IsValueType 指示该类型是否是值类型

Type 方法

方法名称 描述
GetConstructor(), GetConstructors() 返回ConstructorInfo类型,用于取得该类的构造函数的信息
GetEvent(), GetEvents() 返回EventInfo类型,用于取得该类的事件的信息
GetField(), GetFields() 返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
GetInterface(), GetInterfaces() 返回InterfaceInfo类型,用于取得该类实现的接口的信息
GetMember(), GetMembers() 返回MemberInfo类型,用于取得该类的所有成员的信息
GetMethod(), GetMethods() 返回MethodInfo类型,用于取得该类的方法的信息
GetProperty(), GetProperties() 返回PropertyInfo类型,用于取得该类的属性的信息

可以调用这些成员,其方式是调用 TypeInvokeMember() 方法,或者调用 MethodInfo , PropertyInfo 和其他类的 Invoke() 方法。

  1. public class ReflectClass
  2. {
  3. public string Address;
  4. public int Age { get; set; }
  5. public string Sex { get; set; }
  6. public string Name { get; set; }
  7. public ReflectClass() { }
  8. public ReflectClass(string name)
  9. {
  10. this.Name = name;
  11. }
  12. public ReflectClass(string name, string sex)
  13. {
  14. this.Name = name;
  15. this.Sex = sex;
  16. }
  17. public void Show()
  18. {
  19. Console.WriteLine("姓名:" + Name + "\n" + "年龄:" + Age + "\n" + "性别:" + Sex);
  20. }
  21. }

获取所有构造函数

  1. [TestMethod]
  2. public void GetConstructors()
  3. {
  4. Type t = new ReflectClass().GetType();
  5. // 获取类的所有构造函数
  6. ConstructorInfo[] constructorInfos = t.GetConstructors();
  7. foreach (ConstructorInfo ci in constructorInfos)
  8. {
  9. // 获取每个构造函数的参数
  10. ParameterInfo[] parameterInfos = ci.GetParameters();
  11. foreach (ParameterInfo p in parameterInfos)
  12. {
  13. Console.WriteLine(p.ParameterType.ToString() + "\n" + p.Name + "\n");
  14. }
  15. }
  16. Assert.IsTrue(constructorInfos.Length > 0);
  17. }

动态创建对象

  1. [TestMethod]
  2. public void DynamicCreateObject()
  3. {
  4. Type t = typeof(ReflectClass);
  5. Type[] pt = new Type[2];
  6. pt[0] = typeof(string);
  7. pt[1] = typeof(string);
  8. //根据参数类型获取构造函数
  9. ConstructorInfo ci = t.GetConstructor(pt);
  10. //构造Object数组,作为构造函数的输入参数
  11. object[] obj = new object[2] { "wang", "男" };
  12. //调用构造函数生成对象
  13. object @object = ci.Invoke(obj);
  14. //调用生成的对象的方法测试是否对象生成成功
  15. ((ReflectClass)@object).Show();
  16. Assert.IsTrue(true);
  17. }

使用Activator动态创建对象

  1. [TestMethod]
  2. public void ActivatorDynamicCreateObject()
  3. {
  4. Type t = typeof(ReflectClass);
  5. object[] obj = new object[2] { "wang", "男" };
  6. //用Activator的CreateInstance静态方法,生成新对象
  7. object @object = Activator.CreateInstance(t, obj);
  8. ((ReflectClass)@object).Show();
  9. Assert.IsTrue(true);
  10. }

获取类中的Public属性

  1. [TestMethod]
  2. public void GetProperties()
  3. {
  4. Type t = new ReflectClass().GetType();
  5. PropertyInfo[] propertyInfos = t.GetProperties();
  6. foreach (PropertyInfo p in propertyInfos)
  7. {
  8. Console.WriteLine(p.Name);
  9. }
  10. Assert.IsTrue(true);
  11. }

获取类中Public方法

  1. [TestMethod]
  2. public void GetPublicMethod()
  3. {
  4. Type t = new ReflectClass().GetType();
  5. MethodInfo[] mi = t.GetMethods();
  6. foreach (MethodInfo method in mi)
  7. {
  8. Console.WriteLine(method.ReturnType + "|" + method.Name);
  9. }
  10. Assert.IsTrue(true);
  11. }

获取类中Public字段

  1. [TestMethod]
  2. public void GetField()
  3. {
  4. Type t = new ReflectClass().GetType();
  5. FieldInfo[] fieldInfos = t.GetFields();
  6. foreach (FieldInfo fieldInfo in fieldInfos)
  7. {
  8. Console.WriteLine(fieldInfo.Name);
  9. }
  10. Assert.IsTrue(true);
  11. }
  1. [TestMethod]
  2. public void Example_01()
  3. {
  4. ReflectClass rc = new ReflectClass();
  5. Type t = rc.GetType();
  6. object obj = Activator.CreateInstance(t);
  7. FieldInfo address = t.GetField("Address");
  8. address.SetValue(obj, "Beijing");
  9. PropertyInfo name = t.GetProperty("Name");
  10. name.SetValue(obj, "wang", null);
  11. PropertyInfo age = t.GetProperty("Age");
  12. age.SetValue(obj, 20, null);
  13. MethodInfo method = t.GetMethod("Show");
  14. method.Invoke(obj, null);
  15. Console.WriteLine("Address为:" + ((ReflectClass)obj).Address);
  16. Assert.IsTrue(true);
  17. }

Assembly

GetAssembly

  1. [TestMethod]
  2. public void GetAssembly()
  3. {
  4. // 通过程序集名称返回Assembly对象
  5. Assembly assembly = Assembly.Load("CodeSnippet");
  6. // 通过Assembly获取程序集中类(参数必须是类的全名)
  7. Type type = assembly.GetType("CodeSnippet.Csharp.ReflectClass");
  8. Assert.IsNotNull(type);
  9. // 通过Assembly获取程序集中所有的类
  10. Type[] types = assembly.GetTypes();
  11. Assert.IsNotNull(types);
  12. // 通过DLL文件名称返回Assembly对象
  13. warning disable S3885 // "Assembly.Load" should be used
  14. Assembly assembly2 = Assembly.LoadFrom("CodeSnippet.dll");
  15. warning restore S3885 // "Assembly.Load" should be used
  16. // 通过Assembly获取程序集中类(参数必须是类的全名)
  17. Type type2 = assembly2.GetType("CodeSnippet.Csharp.ReflectClass");
  18. Assert.IsNotNull(type2);
  19. // 通过Assembly获取程序集中所有的类
  20. Type[] types2 = assembly2.GetTypes();
  21. Assert.IsNotNull(types2);
  22. }

通过程序集的名称反射

  1. [TestMethod]
  2. public void Example_02()
  3. {
  4. Assembly assembly = Assembly.Load("CodeSnippet");
  5. //参数必须是类的全名
  6. Type t = assembly.GetType("CodeSnippet.Csharp.ReflectClass");
  7. object o = Activator.CreateInstance(t, "男");
  8. MethodInfo mi = t.GetMethod("Show");
  9. mi.Invoke(o, null);
  10. Assert.IsNotNull(o);
  11. }

通过DLL文件全名反射其中的所有类型

  1. [TestMethod]
  2. public void Example_03()
  3. {
  4. warning disable S3885 // "Assembly.Load" should be used
  5. Assembly assembly = Assembly.LoadFrom("CodeSnippet.dll");
  6. warning restore S3885 // "Assembly.Load" should be used
  7. Type[] types = assembly.GetTypes();
  8. foreach (Type t in types)
  9. {
  10. if (t.FullName == "CodeSnippet.Csharp.ReflectClass")
  11. {
  12. object o = Activator.CreateInstance(t);
  13. Assert.IsNotNull(o);
  14. }
  15. }
  16. }

BindingFlags

  1. // Specifies flags that control binding and the way in which the search for members
  2. // and types is conducted by reflection.