请描述在 C# 编程语言中,利用反射(System.Reflection)机制来调用类型的方法(MethodInfo.Invoke)以及读取和写入字段(FieldInfo)的具体操作方式。
考察说明
考查对 C# 反射 API 的掌握程度,包括如何获取类型信息、调用方法和访问字段,以及反射的性能和安全注意事项。
回答思路
- 【回答框架 1】反射的核心是通过 System.Type 对象获取类型的元数据。首先使用 typeof 运算符或 object.GetType() 方法获得 Type。然后可以调用 GetMethod、GetField 等成员获取对应的 MethodInfo 或 FieldInfo。
- 【回答框架 2】调用方法时,先获取 MethodInfo,然后调用其 Invoke 方法,第一个参数是目标对象实例(若为静态方法则为 null),第二个参数是参数对象数组。对于非公共方法,需要指定 BindingFlags 如 NonPublic 和 Instance。
- 【回答框架 3】访问字段时,通过 Type.GetField 或 GetField(name, BindingFlags) 获取 FieldInfo,然后使用 GetValue 方法读取字段值,使用 SetValue 方法设置字段值,同样需要指定绑定标志以访问私有字段。
- 【回答框架 4】如果方法或字段属于泛型类型或存在重载,需要额外处理:泛型方法需要先通过 MakeGenericMethod 构造具体类型,重载方法需通过 GetMethods 过滤参数列表。
- 【回答框架 5】反射会带来性能开销和绕过访问控制的安全风险,在性能敏感场景应避免频繁使用,并注意异常处理(如 TargetInvocationException 和 SecurityException)。
- 【关键点 1】使用 Type.GetMethod 或 Type.GetMethods 获取方法,MethodInfo.Invoke 调用。
- 【关键点 2】使用 Type.GetField 或 Type.GetFields 获取字段,FieldInfo.GetValue/SetValue 读写。
- 【关键点 3】非公共成员需指定 BindingFlags.NonPublic | BindingFlags.Instance。
- 【关键点 4】泛型方法需进行泛型参数填充。
- 【关键点 5】反射性能开销大,且有安全风险,需谨慎使用。
- 【易错点 1】忽略 BindingFlags 会导致无法访问私有成员。
- 【易错点 2】调用有参数的方法时,参数数组顺序或类型错误会引发 ArgumentException。
- 【易错点 3】直接使用反射读取大量数据或高频调用会严重影响性能。