C# 的反射(Reflection)
了解 C# 的反射(Reflection),这是任何 高级 .NET 编程、框架设计、动态元数据访问 的核心技能之一。从一个专业开发工程师角度为你全面讲解 C# 反射,结构如下:
一、什么是反射(Reflection)
二、反射的常用场景
三、核心 API 与用法
四、反射操作:类型、成员、实例、调用
五、实战案例
六、性能问题与安全注意事项
七、权威参考资料
一、什么是反射(Reflection)
反射是一种在运行时动态获取类型信息、创建对象、访问成员(属性、字段、方法)或调用方法的机制。
C# 中,反射主要由 System.Reflection 命名空间提供支持。
简而言之,它允许你写出“动态分析类型”、“运行时调用方法”、“编写框架或通用组件”的代码。
二、反射的常用场景
| 场景 | 示例 |
|---|---|
| 插件机制 | 加载 DLL,识别类和方法并调用 |
| ORM 框架 | 动态读取实体类属性生成 SQL |
| 控制反转(IoC) | 运行时分析构造函数注入依赖 |
| 特性读取 | 如读取 [Route] 特性处理路由 |
| 序列化/反序列化 | 通过属性反射实现 JSON/XML 映射 |
| 单元测试框架 | 查找并执行标记了 [Test] 的方法 |
三、核心 API 与用法
using System;
using System.Reflection;
常用类型:
| 类型 | 描述 |
|---|---|
Type | 类型信息的入口 |
PropertyInfo | 表示属性 |
FieldInfo | 表示字段 |
MethodInfo | 表示方法 |
ConstructorInfo | 构造函数 |
Assembly | 表示一个程序集 |
Activator | 创建对象 |
四、反射操作大全(配代码)
1️⃣ 获取类型信息
Type t1 = typeof(string);
Type t2 = "hello".GetType();
Type t3 = Type.GetType("System.Int32");
2️⃣ 获取类的成员
Type type = typeof(Person);
var props = type.GetProperties(); // 所有公共属性
var fields = type.GetFields(); // 所有公共字段
var methods = type.GetMethods(); // 所有公共方法
3️⃣ 创建对象实例
Type type = typeof(Person);
object obj = Activator.CreateInstance(type);
4️⃣ 访问属性/字段
var prop = type.GetProperty("Name");
prop.SetValue(obj, "小明");
var field = type.GetField("_age", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(obj, 18);
5️⃣ 调用方法
var method = type.GetMethod("SayHello");
method.Invoke(obj, null); // 参数放在 object[] 中
6️⃣ 读取 Attribute 特性
var attr = prop.GetCustomAttribute(typeof(DisplayAttribute));
五、实战案例
✅ 案例:实现一个 Mini 依赖注入容器(构造函数注入)
public class ServiceA { public void Do() => Console.WriteLine("A"); }
public class ServiceB {
private readonly ServiceA _a;
public ServiceB(ServiceA a) { _a = a; }
public void Do() => _a.Do();
}
// 反射式工厂
public class Container {
public object Resolve(Type type)
{
var ctor = type.GetConstructors().First();
var parameters = ctor.GetParameters()
.Select(p => Resolve(p.ParameterType))
.ToArray();
return Activator.CreateInstance(type, parameters);
}
}
// 使用
var container = new Container();
var b = (ServiceB)container.Resolve(typeof(ServiceB));
b.Do(); // 输出 "A"
你可以看到:反射让我们在不知道类型的前提下,动态构造对象并注入依赖。
六、反射的性能和安全注意事项
性能问题
- 反射是慢的:反射比直接调用慢 10~100 倍,不建议频繁调用。
- 可通过 缓存 Type/MethodInfo 或使用 Expression Tree、委托 代替反射优化性能。
安全问题
- 不要对外部不可信 DLL 使用反射加载与执行方法,防止 RCE(远程代码执行)攻击。
- 谨慎使用
BindingFlags.NonPublic修改私有成员,可能破坏封装性。
七、权威资料参考链接
- 📘 .NET 反射官方文档
- 📘 System.Type 类 – Microsoft
- 📘 Activator 类
- 📘 PropertyInfo 类
- 📘 MethodInfo 类
- 🔍 Stack Overflow:如何用反射高效调用方法
总结一句话
反射 = 类型+成员+动态执行+特性处理
是你构建 插件框架、序列化器、IOC 容器、MVC 路由、ORM 框架 的核心能力。
更多详细内容,请关注其他相关文章!