C# 的反射(Reflection)
                           
天天向上
发布: 2025-04-19 09:52:57

原创
548 人浏览过

了解 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 修改私有成员,可能破坏封装性。

七、权威资料参考链接


总结一句话

反射 = 类型+成员+动态执行+特性处理
是你构建 插件框架、序列化器、IOC 容器、MVC 路由、ORM 框架 的核心能力。


更多详细内容,请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *