news 2026/7/14 8:51:41

C# 反射

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C# 反射

C# 中的反射(Reflection)是 .NET 提供的一种强大机制,允许程序在运行时检查、分析和操作类型(类、结构、接口、方法、属性等)的元数据,并动态创建对象、调用方法、访问字段或属性。它主要通过System.Reflection命名空间中的类实现。


一、反射的核心用途

  1. 动态加载程序集(Assembly)
  2. 获取类型信息(Type)
  3. 创建对象实例(Activator / ConstructorInfo)
  4. 调用方法(MethodInfo.Invoke)
  5. 读写属性或字段(PropertyInfo / FieldInfo)
  6. 检查特性(Attribute)
  7. 实现插件系统、ORM、序列化框架等

二、基础使用步骤

1. 获取 Type 对象

// 方法1:通过 typeofTypetype1=typeof(string);// 方法2:通过对象的 GetType()stringstr="hello";Typetype2=str.GetType();// 方法3:通过类型全名从 Assembly 加载Typetype3=Type.GetType("System.String");// 方法4:从程序集加载Assemblyassembly=Assembly.LoadFrom("MyLibrary.dll");Typetype4=assembly.GetType("MyNamespace.MyClass");

注意:Type.GetType("...")只能加载当前应用域中已加载或 mscorlib/System 中的类型,跨程序集需指定完整名称(含 Assembly 信息)。


2. 创建对象实例

使用Activator.CreateInstance
Typetype=typeof(Person);objectobj=Activator.CreateInstance(type);// 调用无参构造函数// 带参数构造objectobj2=Activator.CreateInstance(type,"Alice",30);
使用ConstructorInfo
ConstructorInfoctor=type.GetConstructor(newType[]{typeof(string),typeof(int)});objectinstance=ctor.Invoke(newobject[]{"Bob",25});

3. 调用方法

Typetype=typeof(Calculator);objectcalc=Activator.CreateInstance(type);// 获取方法MethodInfomethod=type.GetMethod("Add");// 调用实例方法intresult=(int)method.Invoke(calc,newobject[]{10,20});// 调用静态方法MethodInfostaticMethod=type.GetMethod("Multiply");intstaticResult=(int)staticMethod.Invoke(null,newobject[]{5,6});

如果方法是泛型,需先调用MakeGenericMethod()


4. 访问属性(Property)

Typetype=typeof(Person);objectperson=Activator.CreateInstance(type);// 设置属性PropertyInfonameProp=type.GetProperty("Name");nameProp.SetValue(person,"Charlie");// 获取属性值stringname=(string)nameProp.GetValue(person);

5. 访问字段(Field)

FieldInfofield=type.GetField("_age",BindingFlags.NonPublic|BindingFlags.Instance);field.SetValue(person,28);intage=(int)field.GetValue(person);

注意:私有成员需要BindingFlags.NonPublic


6. 获取所有成员

Typetype=typeof(MyClass);// 所有公共方法MethodInfo[]methods=type.GetMethods();// 所有公共属性PropertyInfo[]props=type.GetProperties();// 所有字段(包括私有)FieldInfo[]fields=type.GetFields(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);// 所有构造函数ConstructorInfo[]ctors=type.GetConstructors();

7. 检查和读取特性(Attribute)

[DisplayName("用户实体")]publicclassUser{}// 检查是否有某个 AttributeboolhasAttr=type.IsDefined(typeof(DisplayNameAttribute),false);// 获取 Attribute 实例varattr=(DisplayNameAttribute)type.GetCustomAttribute(typeof(DisplayNameAttribute));Console.WriteLine(attr.DisplayName);// 输出:"用户实体"

三、常用 BindingFlags 枚举值

标志说明
Public公共成员(默认)
NonPublic私有/受保护成员
Instance实例成员
Static静态成员
DeclaredOnly仅当前类型声明的成员(不包括继承)

示例:

type.GetMethod("PrivateMethod",BindingFlags.NonPublic|BindingFlags.Instance);

四、性能注意事项

  • 反射比直接调用慢很多(可能慢 10~100 倍),因为涉及类型查找、安全检查、装箱/拆箱等。
  • 避免在高频循环中使用反射
  • 可缓存 MethodInfo / PropertyInfo 等以提升性能。
  • 考虑使用委托(如Delegate.CreateDelegate)或表达式树(Expression)优化
  • .NET Core / .NET 5+ 引入了System.Reflection.Emitsource generator等更高效替代方案。

五、实际应用场景举例

1. 通用对象拷贝器

publicstaticvoidCopyProperties(objectsource,objecttarget){varsourceType=source.GetType();vartargetType=target.GetType();foreach(varpropinsourceType.GetProperties()){vartargetProp=targetType.GetProperty(prop.Name);if(targetProp!=null&&targetProp.CanWrite){targetProp.SetValue(target,prop.GetValue(source));}}}

2. 插件系统

Assemblyplugin=Assembly.LoadFrom("Plugin.dll");TypepluginType=plugin.GetTypes().FirstOrDefault(t=>typeof(IPlugin).IsAssignableFrom(t));IPlugininstance=(IPlugin)Activator.CreateInstance(pluginType);instance.Execute();

3. ORM 映射(如将 DataTable 转为对象)

publicstaticTToObject<T>(DataRowrow)whereT:new(){Tobj=newT();Typetype=typeof(T);foreach(DataColumncolinrow.Table.Columns){PropertyInfoprop=type.GetProperty(col.ColumnName);if(prop!=null&&row[col]!=DBNull.Value)prop.SetValue(obj,row[col]);}returnobj;}

六、总结

优点缺点
高度灵活,支持运行时动态行为性能开销大
实现通用框架(如 DI、AOP、序列化)代码可读性降低
支持插件、脚本扩展容易引发运行时异常(如拼写错误)
可用于调试、测试工具不支持 AOT 编译(如 Native AOT)的部分场景

建议:仅在必要时使用反射,并做好异常处理(如NullReferenceExceptionTargetExceptionMissingMethodException等)。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 19:23:22

Arbess从基础到实践(12) - 集成GitLab实现C++项目自动化部署

Arbess 是一款开源免费的 CICD 工具&#xff0c;支持免费私有化部署&#xff0c;一键部署零配置。本文将详细介绍如何安装Arbess、GitLab&#xff0c;创建流水线实现 C 项目自动化构建并主机部署。 1、GitLab 安装与配置 本章节将介绍如何使用CentOS9搭建Gitlab服务器&#x…

作者头像 李华
网站建设 2026/7/14 5:16:58

Flutter状态管理终极指南:5种主流方案深度对比

一、为什么90%的Flutter开发者都搞不定状态管理&#xff1f; 在开发Flutter应用时&#xff0c;你是否遇到过这些问题&#xff1a; &#x1f92f; 状态分散&#xff1a;数据在多个页面间传递像"击鼓传花"&#x1f41e; 性能瓶颈&#xff1a;一个状态更新导致整个页面…

作者头像 李华
网站建设 2026/7/13 4:17:19

芸光讲师:AI 搜索 GEO 增长领路人,抢先机系统核心创始人

当企业还在为 “GEO 优化没流量、内容不被 AI 推荐、投入回报不可控” 焦虑时&#xff0c;芸光以 13 年企业服务沉淀 AI 搜索全周期实战经验&#xff0c;成为打破行业痛点的核心领路人。他不仅是南京芯芸信息科技创始人、抢先机 AI 系统核心研发者&#xff0c;更是国内 AI 搜索…

作者头像 李华
网站建设 2026/7/14 14:06:36

20个大厂js面试题

以下是20个涵盖不同难度和知识点的JavaScript大厂面试题&#xff0c;包含核心概念、异步、框架、性能等方向&#xff1a; 一、基础与核心概念 解释JavaScript中的事件循环&#xff08;Event Loop&#xff09;机制&#xff0c;并说明宏任务与微任务的区别。什么是闭包&#xff…

作者头像 李华
网站建设 2026/7/14 11:43:01

水闸安全自动化监测系统主要应用场景

水闸安全自动化监测系统是集现代传感技术、数据通信技术、计算机技术和信息处理技术于一体的综合性安全监测平台。该系统通过在水闸关键部位布设各类传感器&#xff0c;实现对水闸运行状态参数的实时、连续、自动采集&#xff0c;并通过数据传输网络将监测数据发送至中心数据库…

作者头像 李华
网站建设 2026/7/14 5:07:45

transformer模型详解进阶篇:Qwen3-32B注意力机制剖析

Qwen3-32B注意力机制深度解析&#xff1a;从长上下文到高效推理的工程实践 在大模型落地进入深水区的今天&#xff0c;一个核心问题愈发凸显&#xff1a;如何在有限算力下实现接近顶级闭源模型的语言理解与生成能力&#xff1f;尤其当企业面对真实业务场景——比如分析整本法律…

作者头像 李华