C# 反射(加载外部DLL)

C# 反射(加载外部DLL)
一、反射核心概念必背1. 传统调用类库方式缺点正常使用第三方类库必须满足三步1、项目添加【程序集引用】2、代码引入【命名空间 using】3、new 实例化对象调用成员缺点耦合度极高缺一不可不能动态扩展2. 反射的定义反射程序运行时动态加载外部DLL文件无需引用、无需命名空间即可读取类的属性、调用类的方法。核心作用运行时动态解析程序集、动态创建对象、动态调用成员3. 反射必备命名空间using System.Reflection;//反射核心using System.IO;//文件路径读取二、本次案例结构说明1、类库项目 ClassLibrary1生成dll包含两个属性Name、ID带默认值两个方法Test1无返回值、Test2有返回值2、主项目 _8反射反射调用端不添加任何项目引用直接加载 dll 文件完成调用。三、反射固定五步流程超级重点、必考第一步拼接DLL文件物理路径第二步Assembly.LoadFile() 加载外部程序集第三步CreateInstance() 动态创建类对象第四步GetType() 获取当前类的元数据类型第五步遍历成员区分【属性/方法】分别读取、调用四、完整代码 逐行超细解析1、被反射的类库代码ClassLibrary1namespace ClassLibrary1 { public class Class1 { //自动属性设置默认值 public string Name { get; set; } 梅西; public string ID { get; set; } 001; //无返回值方法 public void Test1() { Console.WriteLine(Test1方法); } //有返回值方法 public string Test2() { Console.WriteLine(Test2方法); return test2方法; } } }2、主程序反射代码 逐行解析using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; namespace _8反射 { internal static class Program { [STAThread] static void Main() { // 打印当前程序的类型 Console.WriteLine(typeof(Program)); // 1、拼接DLL路径 // Environment.CurrentDirectory程序运行目录 // ../../ 返回上两级目录找到libs文件夹下的dll string path Path.Combine(Environment.CurrentDirectory, ../../libs/ClassLibrary1.dll); // 2、加载外部DLL程序集 Assembly sbly Assembly.LoadFile(path); // 3、反射创建类实例 // 参数格式命名空间.类名 // 等同于ClassLibrary1.Class1 class1 new ClassLibrary1.Class1(); object class1 sbly.CreateInstance(ClassLibrary1.Class1); // 4、获取对象的Type元数据 Type type class1.GetType(); Console.WriteLine(type); // 5、获取类中所有成员属性、方法 MemberInfo[] arr type.GetMembers(); //遍历所有成员 foreach (MemberInfo item in arr) { // 判断当前成员是否为【属性】 if (item.MemberType MemberTypes.Property) { // 父类转子类转为属性信息对象 PropertyInfo info item as PropertyInfo; // GetValue(对象)读取属性值 Console.WriteLine(info.GetValue(class1) ); } // 判断当前成员是否为【方法】 if (item.MemberType MemberTypes.Method) { // 转为方法信息对象 MethodInfo info item as MethodInfo; // 调用Test2方法 if (info.Name Test2) { // Invoke(实例对象, 参数数组) info.Invoke(class1, null); } // 调用Test1方法 if (info.Name Test1) { info.Invoke(class1, null); } } } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }五、核心类与方法详解1、Assembly 程序集Assembly.LoadFile(路径)根据文件路径加载完整 DLLCreateInstance(命名空间.类名)动态 new 对象返回 object2、Type 类型元数据存储一个类的所有信息属性、方法、字段、构造函数GetMembers()获取当前类的所有公共成员3、MemberInfo 成员基类所有属性、方法的父类需要通过 MemberType 判断具体类型MemberTypes.Property属性MemberTypes.Method方法4、PropertyInfo 属性操作GetValue(对象)读取属性值SetValue(对象,值)修改属性值5、MethodInfo 方法操作Invoke(对象, 参数数组)执行方法无参数第二个参数传 null六、程序运行输出结果_8反射.ProgramClassLibrary1.Class1梅西001Test2方法Test1方法七、重难点 易错点总结考试常考1、反射运行时生效编译时不需要认识目标DLL2、CreateInstance 参数必须是命名空间.类名完整字符串写错直接为null3、Invoke 调用实例方法必须传对象静态方法传 null4、GetMembers 包含所有公共成员需要手动区分属性/方法5、DLL路径错误会直接抛异常路径必须准确八、一句话总结背诵反射就是运行时加载外部DLL、动态创建对象、动态读取属性、动态调用方法实现项目零引用、低耦合、插件式开发。