欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 深入理解 C# 反射:基础原理与实际应用

深入理解 C# 反射:基础原理与实际应用

2025/3/12 15:53:18 来源:https://blog.csdn.net/weixin_48916144/article/details/146171224  浏览:    关键词:深入理解 C# 反射:基础原理与实际应用

反射(Reflection)是 .NET 中一项强大的功能,它允许程序在运行时动态获取类型信息、创建对象、调用方法、以及访问和修改类的成员(字段、属性等)。反射提供了极大的灵活性和可扩展性,特别适用于那些需要在运行时动态操作类型的场景。然而,反射也有性能开销,因此在使用时需要谨慎。本文将详细介绍 C# 反射的基本用法,包括如何获取类型信息、动态创建对象、动态调用方法、访问和修改字段/属性的值,以及获取程序集和模块信息。

1. 获取类型信息(字段、属性、方法等)

反射允许你在运行时获取对象的类型信息,进而访问类的字段、属性、方法等成员。你可以通过 Type 类来获取类型信息,利用该信息进行动态操作。

示例:获取字段、属性和方法信息
using System;
using System.Reflection;public class MyClass
{public int Field1 = 10;private string Field2 = "Hello";public int MyProperty { get; set; }public void MyMethod(){Console.WriteLine("Method executed!");}private void PrivateMethod(){Console.WriteLine("Private method executed!");}
}class Program
{static void Main(){MyClass obj = new MyClass();Type type = obj.GetType(); // 获取类型信息// 获取字段信息FieldInfo field1 = type.GetField("Field1");Console.WriteLine("Field1: " + field1.GetValue(obj));  // 输出:Field1: 10// 获取私有字段信息FieldInfo field2 = type.GetField("Field2", BindingFlags.NonPublic | BindingFlags.Instance);Console.WriteLine("Field2: " + field2.GetValue(obj));  // 输出:Field2: Hello// 获取属性信息PropertyInfo property = type.GetProperty("MyProperty");Console.WriteLine("MyProperty: " + property.GetValue(obj));  // 输出:MyProperty: 0 (默认值)// 获取方法信息MethodInfo method = type.GetMethod("MyMethod");method.Invoke(obj, null);  // 输出:Method executed!// 获取私有方法信息MethodInfo privateMethod = type.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);privateMethod.Invoke(obj, null);  // 输出:Private method executed!}
}

在上面的代码中,Type.GetType() 用来获取类的类型信息,GetField(), GetProperty(), GetMethod() 等方法可以帮助你获取字段、属性和方法的信息。通过 BindingFlags.NonPublic 可以访问私有成员。

2. 动态创建对象

反射使得在运行时动态创建对象成为可能。你可以通过类型信息来创建对象,甚至是使用带参数的构造函数来创建对象。

示例:动态创建对象并调用方法
using System;public class MyClass
{public MyClass() { Console.WriteLine("Constructor called!"); }public void DisplayMessage() { Console.WriteLine("Hello from MyClass!"); }
}class Program
{static void Main(){Type type = typeof(MyClass);// 动态创建对象object obj = Activator.CreateInstance(type);// 调用方法MethodInfo method = type.GetMethod("DisplayMessage");method.Invoke(obj, null);  // 输出:Hello from MyClass!}
}

在这个示例中,Activator.CreateInstance() 方法用来动态创建 MyClass 类的实例,之后通过反射调用了 DisplayMessage 方法。

3. 动态调用方法

通过反射,你可以在运行时动态调用对象的公共或私有方法。即使方法的名称、参数等信息在编译时未知,也可以通过反射来动态调用。

示例:动态调用公共和私有方法
using System;
using System.Reflection;public class MyClass
{private void PrivateMethod(){Console.WriteLine("Private method called!");}public void PublicMethod(){Console.WriteLine("Public method called!");}
}class Program
{static void Main(){MyClass obj = new MyClass();Type type = obj.GetType();// 调用公共方法MethodInfo publicMethod = type.GetMethod("PublicMethod");publicMethod.Invoke(obj, null);  // 输出:Public method called!// 调用私有方法MethodInfo privateMethod = type.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);privateMethod.Invoke(obj, null);  // 输出:Private method called!}
}

在上面的代码中,我们使用 MethodInfo.Invoke() 方法动态调用了公共方法 PublicMethod 和私有方法 PrivateMethod

4. 访问和修改字段、属性的值

反射不仅能够读取对象的字段和属性,还能修改它们的值。你可以通过反射动态地访问和修改字段或属性,无论它们是公共的还是私有的。

示例:访问和修改字段、属性的值
using System;
using System.Reflection;public class MyClass
{public int PublicField = 100;private string PrivateField = "Hello";public int MyProperty { get; set; }
}class Program
{static void Main(){MyClass obj = new MyClass();Type type = obj.GetType();// 获取和修改字段值FieldInfo publicField = type.GetField("PublicField");Console.WriteLine("PublicField: " + publicField.GetValue(obj));  // 输出:PublicField: 100publicField.SetValue(obj, 200);Console.WriteLine("PublicField (after modification): " + publicField.GetValue(obj));  // 输出:PublicField (after modification): 200// 获取私有字段值FieldInfo privateField = type.GetField("PrivateField", BindingFlags.NonPublic | BindingFlags.Instance);Console.WriteLine("PrivateField: " + privateField.GetValue(obj));  // 输出:PrivateField: HelloprivateField.SetValue(obj, "New Value");Console.WriteLine("PrivateField (after modification): " + privateField.GetValue(obj));  // 输出:PrivateField (after modification): New Value// 获取和修改属性值PropertyInfo property = type.GetProperty("MyProperty");property.SetValue(obj, 50);Console.WriteLine("MyProperty: " + property.GetValue(obj));  // 输出:MyProperty: 50}
}

在这个示例中,FieldInfo.GetValue()PropertyInfo.GetValue() 方法用于读取字段或属性的值,FieldInfo.SetValue()PropertyInfo.SetValue() 方法则用于修改字段或属性的值。

5. 获取程序集和模块信息

反射还可以用于获取当前程序集中所有的类型、方法、属性等信息。程序集(Assembly)是包含类型定义的容器,而模块(Module)是程序集中的组成部分。通过反射,可以获取程序集和模块的信息。

示例:获取程序集和模块信息
using System;
using System.Reflection;class Program
{static void Main(){// 获取当前程序集Assembly assembly = Assembly.GetExecutingAssembly();Console.WriteLine("Assembly: " + assembly.FullName);// 获取程序集中的所有类型Console.WriteLine("\nTypes in Assembly:");foreach (Type type in assembly.GetTypes()){Console.WriteLine(type.FullName);}// 获取模块信息Console.WriteLine("\nModules in Assembly:");foreach (Module module in assembly.GetModules()){Console.WriteLine("Module: " + module.Name);}}
}

在这个示例中,使用 Assembly.GetExecutingAssembly() 获取当前程序的程序集信息,通过 GetTypes() 方法列出程序集中的所有类型,GetModules() 获取程序集中的模块信息。

6. 总结

反射是 C# 中非常强大且灵活的功能,它允许程序在运行时动态获取类型信息、创建对象、调用方法、访问和修改字段及属性的值。常见的反射用途包括:

  1. 获取类型信息:通过 Type 获取类的字段、属性、方法等信息。
  2. 动态创建对象:使用 Activator.CreateInstance() 动态创建对象。
  3. 动态调用方法:通过 MethodInfo.Invoke() 动态调用对象的方法。
  4. 访问和修改字段/属性:使用反射读取和修改对象的字段或属性值。
  5. 获取程序集和模块信息:通过反射获取程序集和模块的详细信息。

尽管反射提供了极大的灵活性,但由于其性能开销较大,因此应谨慎使用,尤其是在性能要求较高的场景中。反射通常用于需要高度灵活性和可扩展性的场景,例如插件框架、动态代理和序列化等。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词