本文共 5159 字,大约阅读时间需要 17 分钟。
反射(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(对象关系映射)中。
// 加载类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 类中。
// 加载类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/