C#--反射

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)、依赖注入等技术,充分发挥反射的灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值