C# 反射(Reflection)是一种强大的机制,它允许程序在运行时访问和操作 .NET 程序集中的类型和成员。
获取程序集、模块 和类型成员信息,三者关系介绍请查看。
反射的核心概念是 Type 对象。Type 对象表示一个 .NET 类型,并提供用于访问该类型及其成员的方法和属性。
以下是一些常用的 Type 对象方法:
/// <summary>
/// 获取程序集信息
/// </summary>
public static void GetAssemblyInfo()
{
// 获取当前程序集
Assembly assembly = Assembly.GetExecutingAssembly();
//获取dll程序集
Assembly assembly2 = Assembly.LoadFrom("Note.Basic.dll");
//获取程序集下的类型信息
var typesInfo= assembly.DefinedTypes;
//获取程序集下的模块信息
var modules = assembly.GetLoadedModules();//.GetModules();
foreach (var module in modules)
{
//获取模块下的类型信息, 不是Com和嵌套类型
var types= module.GetTypes().Where(p=>p.Namespace.StartsWith("Note")&&
p.IsCOMObject==false&&!p.IsNested
);
}
}
/// <summary>
/// 获取类型信息
/// </summary>
public static void GetTypeInfo()
{
// 获取 Person 类型的 Type 对象
Type personType = Type.GetType("Note.Basic.Person");
// 获取 Person 类型的名称
string typeName = personType.FullName;
Console.WriteLine("Type name: {0}", typeName);
// 获取 Person 类型的字段
FieldInfo[] fields = personType.GetFields();
foreach (FieldInfo field in fields)
{
MessageBox.Show(string.Format("Field: {0} ({1})", field.Name, field.FieldType.Name));
}
// 获取 Person 类型的属性
PropertyInfo[] properties = personType.GetProperties();
foreach (PropertyInfo property in properties)
{
MessageBox.Show(string.Format("Property: {0} ({1})", property.Name, property.PropertyType.Name));
}
// 获取 Person 类型的构造函数
ConstructorInfo[] constructors = personType.GetConstructors();
foreach (ConstructorInfo constructor in constructors)
{
ParameterInfo[] parameters = constructor.GetParameters();
MessageBox.Show(string.Format("Constructor: {0}({1})", constructor.Name, string.Join(", ", parameters.Select(p => p.ParameterType.Name))));
}
// 获取 Person 类型的 SayHello 方法
MethodInfo sayHelloMethod = personType.GetMethod("Print");
MessageBox.Show(string.Format("Method: {0}({1})", sayHelloMethod.Name, string.Join(", ", sayHelloMethod.GetParameters().Select(p => p.ParameterType.Name))));
// 创建 Person 类型的实例
object? personObject = personType.Assembly.CreateInstance("Note.Basic.Person");
// 将 object 对象转换为 Person 对象
Person person = (Person)personObject;
// 设置 Person 对象的属性
person.Name = "John Doe";
person.Age = 30;
// 调用 Person 对象的方法
sayHelloMethod.Invoke(person, null);
}
动态加载类和创建对象: 反射可用于在运行时加载类,而无需显式地引用它们。这对于创建插件和扩展等需要在运行时动态加载代码的应用程序非常有用。
获取类型和对象的信息: 反射可用于获取有关类型和对象的大量信息,包括类型名称、属性、方法、构造函数等。这对于需要根据类型或对象的信息执行操作的应用程序非常有用。
调用方法: 反射可用于调用对象的任何方法,包括私有方法。这对于需要在无法直接访问方法的情况下调用方法的应用程序非常有用。
创建代理对象: 反射可用于创建代理对象,代理对象可以拦截和修改对目标对象的调用。这对于实现日志记录、安全性和其他方面的功能非常有用。
反序列化 JSON 和 XML 等数据格式: 反射可用于反序列化 JSON 和 XML 等数据格式,将数据转换为对象。这对于需要将数据从字符串转换为对象格式的应用程序非常有用。
生成代码: 反射可用于生成代码,例如代码生成器和序列化工具可以使用反射来根据类型信息生成代码。
反射是一种功能强大的技术,可用于许多不同的应用程序。它可以使您的代码更加灵活、可扩展和可维护。但是,反射也有一些缺点,例如它可能会降低性能并增加安全性风险。因此,在使用反射之前,请务必权衡利弊。