C#中的反射是通过System.Reflection命名空间实现的运行时类型操作机制,允许动态获取类型信息、创建对象、调用方法和访问字段属性。利用Type类可查询类型元数据,Activator.CreateInstance能实例化对象,GetMethod、GetProperty等方法结合BindingFlags可访问公共或私有成员,Invoke用于执行方法。反射还支持加载外部程序集并查找实现特定接口的类型,常用于插件系统、ORM、序列化等场景。但因性能开销较大,建议缓存反射结果或使用Delegate.CreateDelegate生成委托以提升效率。

反射(Reflection)是C#中一种强大的机制,它允许程序在运行时动态获取类型信息、创建对象、调用方法、访问字段和属性。换句话说,通过反射,你可以在不知道具体类型的情况下操作类和对象,这为动态编程提供了极大的灵活性。
什么是C#中的反射?
在编译时,我们通常知道要使用的类型、方法和属性。但在某些场景下,比如插件系统、序列化、ORM框架或依赖注入容器中,类型可能直到运行时才能确定。这时就需要使用反射。
反射的核心是System.Reflection命名空间,它提供了一系列类(如Type、MethodInfo、FieldInfo等),用于查询和操作程序集中的元数据。
常见用途包括:加载程序集并查看其中的类型 动态创建对象实例 调用对象的方法(包括私有方法) 读取或设置字段与属性值 实现通用的序列化/反序列化逻辑
如何使用Type获取类型信息?
Type类是反射的入口点。你可以通过typeof()或对象的GetType()方法获取一个类型的Type实例。
// 获取类型信息Type type = typeof(string);Console.WriteLine(type.Name); // 输出: StringConsole.WriteLine(type.Namespace); // 输出: System// 或从实例获取var list = new List();Type listType = list.GetType();Console.WriteLine(listType.FullName); // System.Collections.Generic.List`1[System.Int32]
通过Type可以获取构造函数、方法、属性、字段等成员信息。
动态创建对象与调用方法
反射允许你在运行时根据类型名创建实例,并调用其方法,即使这些类型在编码时未知。
// 假设有一个简单类public class Calculator{ public int Add(int a, int b) => a + b; private string GetSecret() => "秘密信息";}// 使用反射创建实例并调用公共方法Type calcType = typeof(Calculator);object calc = Activator.CreateInstance(calcType);MethodInfo addMethod = calcType.GetMethod("Add");int result = (int)addMethod.Invoke(calc, new object[] { 5, 3 });Console.WriteLine(result); // 输出: 8
如果你想调用私有方法,需要指定绑定标志:
MethodInfo secretMethod = calcType.GetMethod("GetSecret", BindingFlags.NonPublic | BindingFlags.Instance);string secret = (string)secretMethod.Invoke(calc, null);Console.WriteLine(secret); // 输出: 秘密信息
访问属性和字段
除了方法,反射也能读写属性和字段,无论其访问级别。
public class Person{ public string Name { get; set; } private int age;}Person p = new Person();Type personType = p.GetType();// 设置公共属性PropertyInfo nameProp = personType.GetProperty("Name");nameProp.SetValue(p, "Alice");// 访问私有字段FieldInfo ageField = personType.GetField("age", BindingFlags.NonPublic | BindingFlags.Instance);ageField.SetValue(p, 25);Console.WriteLine(nameProp.GetValue(p)); // AliceConsole.WriteLine(ageField.GetValue(p)); // 25
加载外部程序集进行反射
反射还能加载外部DLL文件,在运行时分析或执行其中的类型。
// 加载外部程序集(假设存在 MyPlugin.dll)Assembly assembly = Assembly.LoadFrom("MyPlugin.dll");// 获取所有类型Type[] types = assembly.GetTypes();foreach (Type t in types){ Console.WriteLine($"找到类型: {t.Name}"); // 查找实现了特定接口的类 if (typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface) { object plugin = Activator.CreateInstance(t); MethodInfo execute = t.GetMethod("Execute"); execute.Invoke(plugin, null); }}
这种机制广泛应用于插件架构或模块化系统中。
性能与使用建议
虽然反射功能强大,但它的性能比直接调用要慢,因为涉及大量的运行时查找和安全检查。
优化建议:缓存Type、MethodInfo等反射对象,避免重复查询 在性能敏感场景中,考虑使用Expression Tree或Delegate.CreateDelegate生成可复用的委托 尽量避免频繁反射调用私有成员,这会破坏封装性且不利于维护
// 使用委托提升性能示例MethodInfo method = typeof(Calculator).GetMethod("Add");var addDelegate = (Func)Delegate .CreateDelegate(typeof(Func), null, method);Calculator calc = new Calculator();int result = addDelegate(calc, 10, 20); // 比Invoke快得多
基本上就这些。C#反射机制让你能在运行时“看透”类型结构并动态交互,是构建灵活、扩展性强的应用程序的重要工具。虽然要注意性能和安全性,但在合适场景下,它几乎是不可替代的。
以上就是C#中的反射(Reflection)是什么?动态编程与C#反射机制实战详解的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1442229.html
微信扫一扫
支付宝扫一扫