C#反射

元数据和反射
(1)元数据(metadata):程序及其类型的数据
(2)反射:运行的程序查看其元数据的行为

Type类
作用:获得反射
特点:抽象类,不能用来实例化对象
程序中的每个类都有一个对应的Type对象,存储这个类的信息(有哪些属性成员等等)
获取Type:

System.Type t = v.GetType();

Type类的常用属性:
(1)Name:类名
(2)Namespace:命名空间
(3)Assembly:程序集类型
Type类获取类的属性,只能获取public:

  System.Type t = v.GetType();
            FieldInfo[] fs = t.GetFields();//using System.Reflection;
            foreach (FieldInfo f in fs) {
                Debug.Log(f);
            }

在这里插入图片描述
另外还有一个GetProperties,用于获取get set访问的属性:

public string name{get;set;}

GetFields用于:

public string name;

Type获取类中的方法:

   System.Type t = v.GetType();
            MethodInfo[] ms = t.GetMethods();
            foreach (MethodInfo m in ms) {
                Debug.Log(m);
            }

在这里插入图片描述

程序集:
获取类的程序集:

Assembly asse = people1.GetType().Assembly;
Debug.Log(asse);

在这里插入图片描述
加载程序集:
在这里插入图片描述

<think>好的,用户现在问的是关于C#反射的介绍。首先,我需要回忆一下反射的基本概念。反射C#中是一个强大的功能,允许程序在运行时获取类型信息并动态调用方法或访问属性。可能用户是刚开始学习C#,或者在做一些需要动态处理类型的项目,比如插件系统或者序列化工具。 接下来,用户的需求可能不仅仅是了解反射是什么,而是想知道它的实际应用场景、常见用法以及需要注意的问题。用户可能在使用反射时遇到了性能问题或者安全问题,所以需要强调这些方面。同时,用户可能希望看到具体的代码示例,这样能更好地理解如何操作。 然后,我需要考虑如何组织内容。首先定义反射,说明其作用。然后分点介绍常见用途,比如类型检查、动态创建对象、调用方法、访问属性和字段等。每个用途最好配上简单的代码示例,让用户一目了然。接着,要提到反射的高级应用,比如特性处理和动态加载程序集,这些都是实际开发中常用的场景。 然后,必须提到反射的优缺点。用户可能知道反射的强大,但不知道其性能开销和安全隐患,这部分需要详细说明,给出优化建议,比如缓存Type对象或使用dynamic关键字。此外,还要提到代码可读性和维护性问题,帮助用户全面了解反射的适用场景。 最后,总结部分要强调反射的灵活性和风险,给出最佳实践建议,比如在必要时使用,并考虑替代方案。这样用户不仅能了解反射,还能在实际项目中合理应用,避免滥用。 现在需要检查是否有遗漏的重要点,比如安全性中的部分信任环境,或者代码示例的正确性。确保示例代码简洁,没有错误。同时,保持语言口语化,避免过于技术化的术语,让初学者也能理解。另外,用户之前的提问是关于ERP多线程的问题,可能用户对性能方面比较敏感,所以反射的性能问题需要特别强调。</think>### C# 反射(Reflection)详解 反射(Reflection)是 C# 中一项强大的功能,允许程序在 **运行时** 动态获取类型信息、访问或操作对象成员(属性、方法、字段等),甚至动态创建类型实例。它是实现灵活性和动态行为的核心机制,但需谨慎使用以避免性能和安全问题。 --- #### **1. 反射的核心用途** - **运行时类型检查**:获取类型元数据(如类名、基类、接口、方法列表等)。 - **动态创建对象**:根据类型名称实例化对象。 - **调用未知方法**:动态执行类中未在编译期绑定的方法。 - **访问私有成员**:突破访问权限限制(需注意安全性)。 - **插件系统开发**:动态加载外部程序集(DLL)并扩展功能。 --- #### **2. 反射的基本操作** ##### **2.1 获取类型信息** 通过 `Type` 类表示类型的元数据,获取方式: ```csharp // 方式1:通过对象获取 Type type1 = obj.GetType(); // 方式2:通过类型名称获取 Type type2 = Type.GetType("System.String"); // 方式3:通过 typeof 运算符 Type type3 = typeof(string); ``` ##### **2.2 动态创建对象** ```csharp Type type = Type.GetType("MyNamespace.MyClass"); object instance = Activator.CreateInstance(type); // 调用无参构造函数 // 调用含参构造函数 object instanceWithArgs = Activator.CreateInstance(type, new object[] { "参数1", 100 }); ``` ##### **2.3 调用方法** ```csharp Type type = instance.GetType(); MethodInfo method = type.GetMethod("MethodName"); method.Invoke(instance, new object[] { 参数1, 参数2 }); // 调用实例方法 // 调用静态方法 MethodInfo staticMethod = type.GetMethod("StaticMethod"); staticMethod.Invoke(null, new object[] { 参数 }); ``` ##### **2.4 访问属性/字段** ```csharp // 获取或设置属性 PropertyInfo prop = type.GetProperty("PropertyName"); object value = prop.GetValue(instance); // 获取值 prop.SetValue(instance, "新值"); // 设置值 // 访问私有字段(需指定 BindingFlags) FieldInfo field = type.GetField("_privateField", BindingFlags.NonPublic | BindingFlags.Instance); object fieldValue = field.GetValue(instance); ``` --- #### **3. 反射的高级应用** ##### **3.1 特性(Attribute)处理** 通过反射读取类或成员上的自定义特性: ```csharp Type type = typeof(MyClass); object[] attrs = type.GetCustomAttributes(typeof(MyAttribute), false); if (attrs.Length > 0) { MyAttribute attr = (MyAttribute)attrs[0]; Console.WriteLine(attr.Description); } ``` ##### **3.2 动态加载程序集** ```csharp // 加载 DLL 文件 Assembly assembly = Assembly.LoadFrom("MyPlugin.dll"); // 遍历程序集中的所有类型 foreach (Type t in assembly.GetTypes()) { if (t.IsClass && !t.IsAbstract) { object plugin = Activator.CreateInstance(t); // 调用插件初始化方法 } } ``` --- #### **4. 反射的优缺点** | **优点** | **缺点** | |------------------------------|---------------------------------------| | 灵活性强,支持动态扩展 | 性能开销大(比直接调用慢 100~1000 倍) | | 实现插件化架构 | 代码可读性差,调试困难 | | 可绕过访问权限(慎用) | 可能引发安全问题(如访问私有成员) | --- #### **5. 性能优化建议** - **缓存 Type 对象**:避免重复调用 `GetType()` 或 `typeof()`。 - **使用 `dynamic` 关键字**:对已知类型动态调用时,`dynamic` 比反射更快。 - **预编译表达式树**:通过 `Expression` 类生成委托,替代反射调用。 ```csharp var method = typeof(MyClass).GetMethod("MyMethod"); var instance = Expression.Parameter(typeof(MyClass), "obj"); var call = Expression.Call(instance, method); var lambda = Expression.Lambda<Action<MyClass>>(call, instance).Compile(); lambda(myInstance); // 快速调用 ``` --- #### **6. 典型应用场景** - **依赖注入框架**:自动解析构造函数参数。 - **ORM 框架**:将数据库字段映射到实体属性。 - **序列化/反序列化**:动态处理 JSON/XML 数据。 - **单元测试工具**:动态执行测试方法。 --- ### **总结** 反射C# 中实现动态编程的利器,但需权衡其灵活性与性能损耗。**在以下场景优先考虑反射**: - 需要动态加载外部代码(如插件)。 - 无法在编译期确定类型(如配置文件驱动)。 - 开发通用框架或工具库。 **避免滥用**:在性能敏感场景(如循环内)或安全关键代码中谨慎使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值