C# 反射(Reflection)是指程序在运行时能够获取自身的信息,并能操作程序集、模块、类型、成员等元数据的能力。通过反射,你可以动态创建对象、调用方法、访问字段和属性,即使在编译时不知道这些类型的具体信息。
一、反射的核心命名空间
反射主要依赖 System.Reflection 命名空间,常用类型包括:
-
Assembly:表示程序集 -
Type:表示类型(类、接口、结构体等) -
MethodInfo:表示方法 -
PropertyInfo:表示属性 -
FieldInfo:表示字段 -
ConstructorInfo:表示构造函数
二、获取Type对象
要使用反射,首先需要获取目标类型的 Type 对象,有以下几种方式:
1.通过类型名获取
Type type = typeof(Person);
2. 通过实例对象获取
Person person = new Person();
Type type = person.GetType();
3.通过程序集和类型名获取(动态加载)
Type type = Type.GetType("Namespace.Person, AssemblyName");
三、动态创建对象
通过反射可以动态创建对象实例:
1.使用无参构造函数
Type type = typeof(Person);
object instance = Activator.CreateInstance(type); // 调用无参构造函数
2.使用带参数的构造函数
Type type = typeof(Person);
// 获取带参数的构造函数(参数类型:string, int)
ConstructorInfo constructor = type.GetConstructor(new[] { typeof(string), typeof(int) });
object instance = constructor.Invoke(new object[] { "Alice", 25 }); // 传入参数
四、访问字段和属性
1.访问字段
Type type = typeof(Person);
object instance = Activator.CreateInstance(type);
// 获取字段信息
FieldInfo field = type.GetField("Name", BindingFlags.Public | BindingFlags.Instance);
// 设置字段值
field.SetValue(instance, "Bob");
// 获取字段值
string name = (string)field.GetValue(instance);
2.访问属性
Type type = typeof(Person);
object instance = Activator.CreateInstance(type);
// 获取属性信息
PropertyInfo property = type.GetProperty("Age");
// 设置属性值
property.SetValue(instance, 30);
// 获取属性值
int age = (int)property.GetValue(instance);
3.调用方法
Type type = typeof(Person);
object instance = Activator.CreateInstance(type);
// 获取方法信息(方法名:SayHello,参数类型:string)
MethodInfo method = type.GetMethod("SayHello", new[] { typeof(string) });
// 调用方法
method.Invoke(instance, new object[] { "World" });
五、调用方法
Type type = typeof(Person);
object instance = Activator.CreateInstance(type);
// 获取方法信息(方法名:SayHello,参数类型:string)
MethodInfo method = type.GetMethod("SayHello", new[] { typeof(string) });
// 调用方法
method.Invoke(instance, new object[] { "World" });
六、操作程序集
1.加载程序集
// 加载当前执行的程序集
Assembly assembly = Assembly.GetExecutingAssembly();
// 加载指定程序集(文件路径)
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");
2.获取程序集中的类型
Assembly assembly = Assembly.GetExecutingAssembly();
Type[] types = assembly.GetTypes(); // 获取所有类型
foreach (Type type in types)
{
Console.WriteLine(type.FullName);
}
七、反射的优缺点
优点:
-
反射提高了程序的灵活性和扩展性。
-
降低耦合性,提高自适应能力。
-
它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺点:
-
性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
-
使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。
八、示例
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age;
public Person() { }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void SayHello(string message)
{
Console.WriteLine($"Hello, {message}! I'm {Name}, {Age} years old.");
}
}
class Program
{
static void Main()
{
// 获取Type
Type personType = typeof(Person);
// 创建实例(带参数构造函数)
object person = Activator.CreateInstance(personType, "Alice", 25);
// 调用方法
MethodInfo sayHello = personType.GetMethod("SayHello");
sayHello.Invoke(person, new[] { "World" });
// 修改字段和属性
FieldInfo ageField = personType.GetField("Age");
ageField.SetValue(person, 30);
PropertyInfo nameProp = personType.GetProperty("Name");
nameProp.SetValue(person, "Bob");
// 再次调用方法
sayHello.Invoke(person, new[] { "Reflection" });
}
}
九、总结
反射是 C# 中强大的特性,适用于需要动态操作类型的场景,但需注意性能和安全性问题。在实际开发中,可结合特性(Attribute)、依赖注入等技术,充分发挥反射的灵活性。
1186

被折叠的 条评论
为什么被折叠?



