C#的反射

  Reflection

一、定义

  反射主要基于System.Assembly类与System.Type类,通过调用方法来获取某一个程序集的相关信息。如类、接口、方法等信息。例如有时候你不知道一个DLL文件里面不知道是个什么东西,你就可以通过Type或者Assembly来调取里面的信息。

二、方法

                                                   Assembly 类的常用属性

公共属性 说明
EntryPoint获取此程序集 的入口点
FullName获取此程序集的显示的名称
Location 获取包含清单已加载文件的路径或位置
MainifestModule获取包含当前程序集清单模块

                                                      Assembly 类的常用方法 

方法说明
GetFiles获取程序集清单文件表中的文件
GetModule获取此程序集的指定模块
GetModules获取作为此程序集的一部分的所有模块
GetType获取表示类型的Type对象
LoadFile加载文件的内容
LoadFrom在已知程序集的文件名或路径等信息加载时加载程序集
LoadModule加载次程序集的内部模块
  
  

                                                      反射空间所包含的类

Assembly类: 通过它可以找到大量的隐藏在在程序集的身份中的信息,如版本信息,区域信息等

ConstructourInfo 类: 用于发现构造函数及调用构造函数。通过Constructors或GetConstructor方法返回

EventInfo 类 :通过它可以找到事件的信息

FieldInfo类:通过它可以找到字段的信息

MethodInfo类:通过它可以找到方法的信息

ParameterInfo类:通过它可以找到参数信息

PropertryInfo类:通过它找到属性的信息

MemberInfo类:它是一个抽象基类,为EventInfo、FieldInfo、MethodInfo、PropertyInfo等类型定义了公共的行为

Module 类:用来访问带有多文件程序集的给定的程序模块

DefaultMemberAttribute类:定义某类型的成员该成员时InvokeMember使用时的默认成员

                                          Type类的常用属性

公共属性说明
IsAbstract获取一个值,通过该值指示Type是否为抽象的并且必须被重写
IsArray获取一个值,通过该值指示Type是否为数组
IsByref获取一个值,通过该值指示Type是否为引用传递
Isclass获取一个值,通过该值指示Type是否为一个类,即不是指类型或接口
IsInterFace获取一个值,通过该值指示Type是否为一个接口,即不是值类型或类
IsSubclassof确定当前的Type表示的类是不是从指定的Type表示的类派生的
MakeArrayType返回一个表示当前类型的一维数组(下限为零)Type的对象
Module获取当前Type定义的模块
Name获取当前成员的名称
Namespace获取Type的命名空间
Reflected获取用于该成员的类对象

                                                Type类的常用方法

方法说明
GetElementType当在派生类中重写时,返回当前的数组、指针或引用类型包含的对象的Type
GetEvent获取由当前的Type声明或继承的特定的事件
GetEvents获取当前的Type声明或继承的特定的事件
GetField获取当前的Type的特定字段
GetFields获取当前的Type的字段
GetInterface获取当前的Type继承或声明的特定接口
GetInterfaces获取当前Type继承或声明的接口
GetMember获取当前的Type的指定成员
GetMembers获取当前的Type 的成员
GetMethod获取当前的Type的指定方法
GetMethods获取当前Type的方法
GetPropertries获取当前Type的属性
GetPropertry获取当前的Type的特定属性
InvokeMember使用指定的绑定约束匹配指定的参数列表,调用指定成员

三、实例

         

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using myns = System.Math;
using System.Data;
using System.Collections;
using System.Reflection;
namespace ConsoleApplication22
{
    class Program
    {
        static void Main(string[] args)
        {


            string classname = "System.Object";
            Console.WriteLine("{0}类",classname);
            Type t=Type.GetType(classname);
            MethodInfo[] m = t.GetMethods();
            Console.WriteLine("{0}的方法个数{1}", t.FullName, m.Length);

            foreach (MethodInfo item in m)
            {
                Console.WriteLine("\t{0}", item.Name);

            }
            FieldInfo[] f = t.GetFields();
            Console.WriteLine("{0}字段的个数{1}", t.FullName, f.Length);
            foreach (FieldInfo item in f)
            {
                Console.WriteLine("\t{0}", item.Name);

            }
            ConstructorInfo[] c = t.GetConstructors();
            Console.WriteLine("{0}的构造函数个数{1}", t.FullName, c.Length);
            foreach (ConstructorInfo item in c)
            {
                Console.WriteLine("\t{0}", item.Name);
            }
            Console.ReadKey();




        }
    }
}

  










<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、付费专栏及课程。

余额充值