C# 反射详解

发布时间:2026/7/14 17:30:02
C# 反射详解 反射Reflection是 C# 中最重要的高级技术之一也是很多框架如 ASP.NET Core、Entity Framework、Unity、依赖注入、ORM工作的基础。一句话理解反射就是程序在运行时查看自己、分析自己、甚至修改自己的能力。例如查看一个类有哪些属性查看有哪些方法动态创建对象动态调用方法动态读取属性动态加载DLL一、为什么需要反射正常情况下我们写代码都是固定的。例如Student stu new Student(); stu.Name 张三; stu.SayHello();这里编译器已经知道Student类Name属性SayHello方法这些都在编译阶段确定。但是如果今天程序运行的时候才知道类叫什么例如数据库里存着Student Teacher Dog Cat程序需要根据字符串创建对象。这时候new Student();已经写不了了。怎么办就需要反射Reflection二、什么是反射反射就是运行时获取类型(Type)的信息。例如一个Student类class Student { public string Name { get; set; } public int Age { get; set; } public void SayHello() { Console.WriteLine(你好); } }利用反射可以得到类名 Student 属性 Name Age 方法 SayHello ToString Equals ...这些信息都可以获取。三、反射核心类反射主要在System.Reflection命名空间。最重要几个类Assembly 程序集DLL、EXE Type 类型 ConstructorInfo 构造函数 MethodInfo 方法 PropertyInfo 属性 FieldInfo 字段 EventInfo 事件真正最核心的是Type四、获取Type对象有三种方法。第一种typeof()Type type typeof(Student);输出Student这是最常用的方法。第二种GetType()对象获取类型。Student stu new Student(); Type type stu.GetType();得到Student第三种Type.GetType()Type type Type.GetType(ConsoleApp.Student);注意必须写完整命名空间。例如ConsoleApp.Student否则找不到。五、获取类的信息例如Type type typeof(Student);获取名称Console.WriteLine(type.Name);输出Student获取完整名称Console.WriteLine(type.FullName);输出ConsoleApp.Student获取命名空间Console.WriteLine(type.Namespace);输出ConsoleApp六、获取所有属性例如PropertyInfo[] properties type.GetProperties();遍历foreach (PropertyInfo p in properties) { Console.WriteLine(p.Name); }输出Name Age获取属性类型Console.WriteLine(p.PropertyType);输出System.String System.Int32七、获取字段(Field)如果是字段public string Name; public int Age;使用FieldInfo[] fields type.GetFields();遍历foreach(FieldInfo f in fields) { Console.WriteLine(f.Name); }八、获取方法获取所有方法MethodInfo[] methods type.GetMethods();遍历foreach(MethodInfo m in methods) { Console.WriteLine(m.Name); }输出SayHello Equals GetHashCode ToString因为父类Object的方法也会显示。九、获取构造函数ConstructorInfo[] constructors type.GetConstructors();遍历输出Student十、利用反射创建对象正常Student stu new Student();反射Type type typeof(Student); object obj Activator.CreateInstance(type);这里obj就是Student对象。可以转换Student stu (Student)obj;如果有构造函数public Student(string name) { Name name; }创建object obj Activator.CreateInstance(type,张三);十一、调用方法例如class Student { public void SayHello() { Console.WriteLine(你好); } }反射Type type typeof(Student); object obj Activator.CreateInstance(type); MethodInfo method type.GetMethod(SayHello); method.Invoke(obj, null);输出你好有参数public void Add(int a,int b) { Console.WriteLine(ab); }调用MethodInfo method type.GetMethod(Add); method.Invoke(obj,new object[]{3,5});输出8十二、读取属性例如Student stu new Student(); stu.Name张三;反射PropertyInfo property type.GetProperty(Name); Console.WriteLine(property.GetValue(stu));输出张三修改属性property.SetValue(stu,李四);输出李四十三、动态调用最经典例如数据库存ClassName Student方法SayHello代码string className ConsoleApp.Student; Type type Type.GetType(className); object obj Activator.CreateInstance(type); MethodInfo method type.GetMethod(SayHello); method.Invoke(obj,null);程序运行后你好完全没有写new Student();十四、加载DLL例如插件Plugin.dll加载Assembly assembly Assembly.LoadFrom(Plugin.dll);获取类型Type type assembly.GetType(Plugin.Test);创建对象object obj Activator.CreateInstance(type);调用方法type.GetMethod(Run).Invoke(obj,null);这就是插件开发最基本原理。十五、反射性能问题反射为什么慢普通调用stu.SayHello();CPU直接知道地址。反射字符串 ↓ 找Type ↓ 找Method ↓ 检查参数 ↓ Invoke ↓ 执行中间多了很多步骤。一般普通调用 100万次 ≈5ms 反射 100万次 ≈150ms~500ms大约慢20100 倍具体取决于运行环境和调用方式。因此不要在高频循环中频繁使用反射。可以缓存Type、MethodInfo甚至结合委托来减少开销。十六、反射的实际应用几乎所有大型 C# 项目都会使用反射例如场景是否使用反射作用ASP.NET Core✅自动发现控制器、ActionEntity Framework Core✅映射实体与数据库JSON 序列化如 System.Text.Json✅读取对象属性进行序列化/反序列化依赖注入DI✅自动创建对象、注入依赖插件系统✅动态加载 DLL 并调用功能Unity✅查找带有特性的脚本、编辑器扩展十七、反射学习路线建议按以下顺序掌握Type获取类型信息类型判断PropertyInfo获取属性读取与设置属性值MethodInfo查找并调用方法传递参数、处理返回值FieldInfo访问字段ConstructorInfo调用不同构造函数创建对象Assembly加载 DLL动态发现类型Attribute特性自定义特性使用反射读取特性这是反射最重要的应用之一总结可以把反射理解为下面这张关系图程序集Assembly │ ▼ Type类型 │ ┌──────┼─────────────┐ ▼ ▼ ▼ 属性 方法 构造函数 PropertyInfo MethodInfo ConstructorInfo │ │ │ ▼ ▼ ▼ 读写属性 调用方法 创建对象**掌握建议**如果你正在系统学习 C#建议先熟练掌握委托、事件、泛型再深入学习反射 特性Attribute。这两者结合后你就能理解很多现代 C# 框架的底层实现原理。