C#零基础通关第十四篇:吃透反射机制,看懂框架底层、实现动态编程与项目解耦
上一篇我们彻底掌握了C# 文件与IO流操作搞定了本地文件读写、数据持久化、日志工具封装补齐了本地数据处理的核心能力能够独立完成项目数据存储、文件管理等落地业务。截止目前我们学的所有语法、类、方法、对象都是编译期固定写死的代码写什么程序就执行什么无法在程序运行过程中动态修改、动态创建、动态调用。但我们日常使用的ASP.NET Core框架、ORM实体映射、依赖注入、配置绑定、插件化开发全部可以实现运行时动态创建对象、动态调用方法无需硬编码。实现这一切的核心黑科技就是本篇的核心知识点——反射Reflection。反射是C#从基础开发进阶高阶架构开发的分水岭是看懂所有框架底层原理、实现项目解耦、灵活拓展的核心基石零基础手把手带你彻底吃透告别只会写硬编码业务代码的阶段。一、反射核心认知到底什么是反射1. 通俗理解反射正常开发我们提前知道类的所有信息编译期直接 new 对象、调用方法、访问属性。反射开发程序运行时主动去反向解剖一个类获取它的类名、属性、字段、方法、构造函数并且可以动态创建对象、动态调用方法、动态赋值取值。反射本质运行时动态获取类的元数据动态操作类的所有成员。2. 为什么必须学反射没有反射就没有现代化.NET框架反射的核心价值无可替代框架底层核心DI依赖注入、MVC控制器映射、EF实体映射、配置绑定全部基于反射实现彻底解耦无需硬编码new对象通过配置、字符串即可动态创建实例降低代码耦合度通用工具封装实体映射、数据拷贝、日志记录、自动序列化一套代码适配所有实体类插件化开发运行时加载外部程序集动态执行功能无需修改源码重启项目。3. 反射核心命名空间所有反射操作都依赖以下核心命名空间是反射开发的必备引用usingSystem.Reflection;二、反射核心类必须掌握的三大核心对象反射的所有操作都围绕这三个核心类展开看懂这三个类就掌握了80%的反射语法。核心类作用Type存储一个类的所有元数据类名、属性、方法、构造函数、字段反射的核心入口PropertyInfo封装类的属性信息支持动态赋值、动态取值MethodInfo封装类的方法信息支持动态调用任意方法三、基础实战1三种方式获取Type类型获取Type对象是所有反射操作的第一步C#提供三种常用获取方式适配不同场景。先定义一个测试实体类后续所有案例统一使用// 测试实体类publicclassStudent{publicintId{get;set;}publicstringName{get;set;}// 无参构造publicStudent(){}// 有参构造publicStudent(intid,stringname){Idid;Namename;}// 测试方法publicvoidShowInfo(){Console.WriteLine($学生ID{Id}姓名{Name});}publicintGetScore(ints){returns;}}1. 类型.GetType() —— 对象实例获取StudentstunewStudent();Typetypestu.GetType();2. typeof(类型) —— 直接通过类名获取最常用Typetypetypeof(Student);3. Assembly获取 —— 字符串全限定名获取框架常用// 通过程序集类全名动态获取类型无需引用实体TypetypeAssembly.GetExecutingAssembly().GetType(命名空间.Student);场景区别前两种适合已知类的反射操作第三种适合框架动态加载、插件化开发。四、基础实战2反射动态创建对象传统写法编译期 new Student()反射写法运行时动态实例化对象无需硬编码构造。1. 调用无参构造创建对象Typetypetypeof(Student);// 动态创建无参实例objectstuObjActivator.CreateInstance(type);StudentstustuObjasStudent;2. 调用有参构造创建对象Typetypetypeof(Student);// 传入构造参数动态调用有参构造objectstuObjActivator.CreateInstance(type,1001,张三);StudentstustuObjasStudent;stu.ShowInfo();核心优势运行时根据参数、配置动态决定创建哪个类的对象彻底摆脱硬编码。五、核心实战1反射动态操作属性赋值/取值项目中最高频的反射场景通用实体赋值、数据拷贝、DTO映射无需手写每个属性的赋值代码。Typetypetypeof(Student);StudentstunewStudent();// 1. 获取指定属性PropertyInfonameProptype.GetProperty(Name);PropertyInfoidProptype.GetProperty(Id);// 2. 动态给属性赋值nameProp.SetValue(stu,李四);idProp.SetValue(stu,1002);// 3. 动态获取属性值objectnameValnameProp.GetValue(stu);objectidValidProp.GetValue(stu);Console.WriteLine($反射赋值结果{idVal}{nameVal});炸裂优势不管实体有多少个属性不用逐行赋值一套反射代码通用所有实体是ORM、数据映射的底层原理。六、核心实战2反射动态调用方法通过MethodInfo获取方法信息运行时动态执行方法支持无参、有参、带返回值方法。Typetypetypeof(Student);StudentstunewStudent(){Id1003,Name王五};// 1. 获取无参方法 ShowInfoMethodInfoshowMethodtype.GetMethod(ShowInfo);// 动态调用无参方法showMethod.Invoke(stu,null);// 2. 获取有参方法 GetScoreMethodInfoscoreMethodtype.GetMethod(GetScore);// 动态传参并调用获取返回值objectresultscoreMethod.Invoke(stu,newobject[]{95});Console.WriteLine($动态调用方法返回分数{result});核心场景框架根据路由动态匹配控制器方法、动态执行配置的功能方法。七、高阶实战通用实体数据拷贝工具企业级复用结合反射特性封装一个万能对象属性拷贝工具支持任意两个相同属性的实体互拷项目可直接复用彻底告别重复赋值代码。publicstaticclassReflectHelper{/// summary/// 通用属性拷贝源对象赋值到目标对象/// /summarypublicstaticvoidCopyProperties(objectsource,objecttarget){TypesourceTypesource.GetType();TypetargetTypetarget.GetType();// 遍历源对象所有属性foreach(PropertyInfosPropinsourceType.GetProperties()){// 匹配目标对象同名属性PropertyInfotProptargetType.GetProperty(sProp.Name);if(tProp!nulltProp.CanWrite){// 动态赋值tProp.SetValue(target,sProp.GetValue(source));}}}}// 调用测试Studentstu1newStudent(){Id1004,Name赵六};Studentstu2newStudent();// 一行代码完成所有属性拷贝ReflectHelper.CopyProperties(stu1,stu2);stu2.ShowInfo();这是企业开发中DTO、VO、实体类数据转换的标准底层实现极简高效、通用性极强。八、反射优缺点与开发场景选型1. 反射核心优点极致灵活运行时动态操作类、对象、属性、方法突破编译期固定代码限制代码高度复用通用工具适配所有实体消灭重复赋值、映射代码架构解耦框架、插件、依赖注入全部依赖反射实现低耦合架构。2. 反射缺点必知存在性能损耗反射需要解析元数据、动态调用比直接硬编码调用慢无编译校验通过字符串匹配类名、方法名编译不报错运行出错代码复杂度提升滥用反射会降低代码可读性增加维护成本。3. 正确使用场景通用工具类、数据映射、实体拷贝、序列化工具框架底层、中间件、插件化、动态配置业务批量统一处理实体属性、自动日志、自动校验场景。开发原则普通简单业务不用反射通用底层、架构层必须用反射。九、新手高频易错坑点必避忘记引用命名空间反射操作必须引用using System.Reflection;否则所有反射类报错字符串名称写错通过字符串获取属性、方法名称大小写敏感编译无提示运行报错忽略属性读写权限没有Set方法的属性无法反射赋值需判断CanWrite频繁反射调用高频循环中直接反射会严重卡顿可通过缓存元数据优化性能滥用反射替代常规代码简单对象创建、方法调用优先硬编码无需过度设计。十、全文核心总结反射本质程序运行时反向解析类的元数据动态创建对象、操作属性、调用方法三大核心类Type获取类信息、PropertyInfo操作属性、MethodInfo调用方法核心能力动态实例化对象、动态赋值取值、动态执行方法实现代码通用和解耦实战价值可封装万能数据拷贝、实体映射、自动工具是框架底层核心原理开发规范架构层、通用工具用反射普通业务慎用兼顾灵活与性能。掌握反射标志着你彻底脱离新手CRUD阶段具备读懂框架、封装底层、搭建架构的高阶开发能力。下期预告下一篇我们将精讲C# 特性Attribute搭配反射实现AOP编程、数据校验、路由标记、日志拦截彻底解锁.NET高阶架构编程