博客
关于我
C# 反射
阅读量:423 次
发布时间:2019-03-06

本文共 5159 字,大约阅读时间需要 17 分钟。

C# 反射操作实用指南

反射(Reflection)是C#中一个强大的工具,允许程序在运行时动态获取和修改类的元数据。以下是通过反射实现的一些常见操作示例,供开发者参考。


一、获取程序集与动态加载

动态加载程序集是反射的基础操作,常用于处理不明事先的动态链接库(DLL)。

// 动态加载程序集Assembly assembly = Assembly.Load("Ruanmou.DB.MySql");// 从特定路径加载完整文件Assembly assembly1 = Assembly.LoadFile(@"D:\ruanmou\online12\20181212Advanced12Course2Reflection\MyReflection\MyReflection\bin\Debug\Ruanmou.DB.MySql.dll");// 从当前路径加载文件Assembly assembly2 = Assembly.LoadFrom("Ruanmou.DB.MySql.dll");// 指定路径加载文件Assembly assembly3 = Assembly.LoadFrom(@"D:\ruanmou\online12\20181212Advanced12Course2Reflection\MyReflection\MyReflection\bin\Debug\Ruanmou.DB.MySql.dll");

二、获取类型、创建对象与调用方法

通过反射可以获取类的类型信息,创建对象并调用方法。

// 获取类型信息Type type = assembly.GetType("Ruanmou.DB.MySql.MySqlHelper");// 创建对象object oDBHelper = Activator.CreateInstance(type);// 类型转换IDBHelper iDBHelper = oDBHelper as IDBHelper;// 调用方法iDBHelper.Query();

三、获取不同构造函数并创建实例

通过反射可以遍历类的构造函数,创建不同参数化的实例。

// 遍历构造函数foreach (ConstructorInfo ctor in type.GetConstructors()){    Console.WriteLine(ctor.Name);    foreach (var parameter in ctor.GetParameters())    {        Console.WriteLine(parameter.ParameterType);    }}// 创建不同参数的实例object oTest1 = Activator.CreateInstance(type);object oTest2 = Activator.CreateInstance(type, new object[] { 123 });object oTest3 = Activator.CreateInstance(type, new object[] { "陌殇" });

四、创建单例实例

反射可以用来破坏单例模式,通过调用私有构造函数创建多个实例。

// 加载类Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");Type type = assembly.GetType("Ruanmou.DB.SqlServer.Singleton");// 创建单例实例Singleton singletonA = (Singleton)Activator.CreateInstance(type, true);Singleton singletonB = (Singleton)Activator.CreateInstance(type, true);Console.WriteLine($"{object.ReferenceEquals(singletonA, singletonD)}");

五、创建泛型类实例

通过反射可以创建泛型类的实例,包括指定参数化类型。

// 加载类Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericClass`3");// 创建泛型实例Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });object oGeneric = Activator.CreateInstance(typeMake);

六、调用重载方法

通过反射可以获取方法信息并调用重载版本。

// 加载类Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest");object oTest = Activator.CreateInstance(type);// 调用不同重载版本MethodInfo method = type.GetMethod("Show1");method.Invoke(oTest, null);MethodInfo method2 = type.GetMethod("Show2");method2.Invoke(oTest, new object[] { 123 });// 进一步演示泛型方法调用MethodInfo method3 = type.GetMethod("Show3");method3.Invoke(oTest, new object[] { 123, "一生为你" });

七、调用私有方法

通过设置正确的绑定属性,可以调用类的私有方法。

// 加载类Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest");object oTest = Activator.CreateInstance(type);// 调用私有方法var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);method.Invoke(oTest, new object[] { "我是老王" });

八、调用泛型方法

通过反射可以调用泛型方法,并指定参数化类型。

// 加载类Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericMethod");object oGeneric = Activator.CreateInstance(type);// 调用泛型方法MethodInfo method = type.GetMethod("Show");var methodNew = method.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });object oReturn = methodNew.Invoke(oGeneric, new object[] { 123, "董小姐", DateTime.Now });

九、调用泛型类的泛型方法

通过反射可以调用泛型类的泛型方法,并传递具体类型参数。

// 加载类Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericDouble`1").MakeGenericType(typeof(int));// 创建实例object oObject = Activator.CreateInstance(type);// 调用泛型方法MethodInfo method = type.GetMethod("Show");method.MakeGenericMethod(typeof(string), typeof(DateTime));method.Invoke(oObject, new object[] { 345, "感谢有梦", DateTime.Now });

十、反射与ORM

通过反射可以操作对象的属性和字段,常用于ORM(对象关系映射)中。

// 加载类Type type = typeof(People);object oPeople = Activator.CreateInstance(type);// 遍历属性foreach (var prop in type.GetProperties()){    Console.WriteLine($"{type.Name}.{prop.Name} = {prop.GetValue(oPeople)}");    if (prop.Name == "Id")    {        prop.SetValue(oPeople, 234);    }    else if (prop.Name == "Name")    {        prop.SetValue(oPeople, "饿了么");    }    Console.WriteLine($"{type.Name}.{prop.Name} = {prop.GetValue(oPeople)}");}// 遍历字段foreach (var field in type.GetFields()){    Console.WriteLine($"{type.Name}.{field.Name} = {field.GetValue(oPeople)}");    if (field.Name == "Description")    {        field.SetValue(oPeople, "并不是外卖,也不是真的饿了");    }    Console.WriteLine($"{type.Name}.{field.Name} = {field.GetValue(oPeople)}");}

十一、反射与DTO(数据传输对象)

通过反射可以将一个对象的属性和字段映射到另一个 DTO 类中。

// 加载类Type typePeople = typeof(People);Type typePeopleDTO = typeof(PeopleDTO);object peopleDTO = Activator.CreateInstance(typePeopleDTO);// 遍历 DTO 的属性foreach (var prop in typePeopleDTO.GetProperties()){    object value = typePeople.GetProperty(prop.Name).GetValue(people);    prop.SetValue(peopleDTO, value);}// 遍历 DTO 的字段foreach (var field in typePeopleDTO.GetFields()){    object value = typePeople.GetField(field.Name).GetValue(people);    field.SetValue(peopleDTO, value);}

以上示例展示了反射在C#中的常见应用场景,包括动态加载、类型操作、单例管理、泛型处理、方法调用等。通过合理使用反射,可以显著提升程序的灵活性和可维护性。

转载地址:http://dviuz.baihongyu.com/

你可能感兴趣的文章
PL/SQL提示“ORA-01722:无效数字,将无效数字查找出来
查看>>
PL/sql语法单元
查看>>
PL/SQL连接远程服务器数据库,出现ORA-12154: TNS: 无法解析指定的连接标识符。
查看>>
pl/sql锁
查看>>
PL2303 Windows 10 驱动项目常见问题解决方案
查看>>
QueryPerformanceCounter与QueryPerformanceFrequency
查看>>
Plaid.com的监控系统如何实现与9600多家金融机构的集成
查看>>
Plain Stock Prediction:基于RNN的股票价格预测工具
查看>>
platform_driver与file_operations两种方法开发led驱动
查看>>
PlatON共识方案详解:应用CBFT共识协议,提高共识效率
查看>>
QueryDict和模型表知识补充
查看>>
Querybase 使用与安装教程
查看>>
Playwright与Selenium的对比:谁是更适合你的自动化测试工具?
查看>>
quarz设置定时器任务的有效时间段_定时器?你知道有几种实现方式吗?
查看>>
PLC、DCS、SCADA的选型
查看>>
PLC中的电子凸轮的简单介绍
查看>>
PLC发展详解-ChatGPT4o作答+匹尔西
查看>>
PLC探针有什么用
查看>>
PLC接线详解
查看>>
PLC数组的使用(西门子)
查看>>