《C#反射机制》

一、什么是反射?

反射是.NET框架提供的一种机制,允许程序在**运行时(Runtime)**获取自身或外部程序集(Assembly)的元数据(Metadata),并能够动态地查看类型信息、创建对象实例、调用方法或访问属性,即使你在编写代码时完全不知道这些类型的存在。

二、形象化比喻:酒店大堂经理与《神奇花名册》

想象你开了一家超大型的豪华酒店:

  • 酒店里有很多 员工 (对应代码里的各种 Controller ,比如负责处理用户业务的 UserController )。
  • 每个员工都有自己擅长的 技能 (对应代码里的 方法/函数 ,比如 Login 登录技能)。
    在 传统的编程方式 中,如果客人想要办理登录,你需要作为老板 直接指名道姓 地在代码里写死安排:"那个负责用户的服务员,你现在去执行'登录'操作!" 在代码里就是直接写死: userController.Login(data);

这种方式很直接,但有一个大问题:如果酒店有一万种服务,客人每次递过来一张写着服务名字的纸条(比如写着"Login"或"Register"),你就得写一万个 if-else 来判断:

  • 如果纸条写着"Login",就叫人去执行 Login();
  • 如果纸条写着"Register",就叫人去执行 Register()......
    这不仅会把你累死,以后每增加一个新功能,你还得跑到这一大堆代码里去加一行,很容易出错。 这时候,"反射机制"就如救世主般降临了!

"反射"就像是大堂经理手里凭空多出来的一本《神奇花名册》 。有了这本花名册,经理不需要提前把员工能干什么全背下来,也不需要写死一堆判断。当客人递过来一张写着"Login"的纸条时,经理只需要做三步:

  1. 看纸条 :确认客人需要的服务名字是 "Login"。
  2. 查名册(这就是反射!) :在《神奇花名册》里搜索 "Login" 这个词,名册会自动检查这个员工身上有没有叫这个名字的技能。
  3. 下指令 :一旦找到,经理直接通过名册对服务员说:"就你了,按照客人的资料去执行刚才找到的那个技能吧!"

简单总结一下 :
反射,就是程序能够在 运行的时候 ,像照镜子一样"看清"自己内部都有哪些方法,并且能够仅仅通过 名字(一段文本字符串) ,就能动态地找到并执行它们,而不需要在写代码时就把调用指令"焊死"。

三、反射的完整流程 (The Complete Flow)

在C#中,使用反射通常遵循一个标准的"五步走"流程: 定位程序集 -> 提取类型 -> 创建实例 -> 操作成员 -> 执行方法 。

1. 动态读取/修改属性

场景描述: 想象你手里有一个 万能遥控器 。你走到一台陌生的电器面前,不需要提前知道它是电视还是空调,只要用遥控器对着它扫一下(反射),就能读取它当前的"温度"或"音量"属性,并且强行修改它。在代码中,这意味着我们不用直接写 对象.属性 = 值 ,而是通过反射"隔空打牛"。

简单代码示例:

csharp 复制代码
using System;
using System.Reflection;

// 这是一个普通的类,相当于一台电器
class Player 
{
    public string Name { get; set; } = "新手村小怪";
}

class Program 
{
    static void Main() 
    {
        // 1. 我们面前有一个玩家对象
        Player p = new Player();
        
        // 2. 拿出万能遥控器(获取它的类型信息 Type)
        Type type = p.GetType();
        
        // 3. 用遥控器扫描它身上有没有叫 "Name" 的属性(按钮)
        PropertyInfo prop = type.GetProperty("Name");
        
        // 4. 读取当前属性的值:按一下遥控器的读取键 GetValue
        object oldName = prop.GetValue(p);
        Console.WriteLine($"修改前,它的名字是:{oldName}");
        
        // 5. 动态修改属性的值:用遥控器 SetValue 把名字改成"满级大佬"
        prop.SetValue(p, "满级大佬");
        
        Console.WriteLine($"修改后,它的名字是:{p.Name}");
    }
}

2. 动态创建对象

场景描述: 普通写代码就像手工捏泥人,你必须在代码里明确写死 new 泥人() 。而反射就像一台 全自动 3D 打印机 。你不需要自己动手捏,只需要把"图纸"(类的类型)输入进打印机,打印机( Activator )就会自动帮你把实物(对象)造出来。

简单代码示例:

csharp 复制代码
using System;

// 这是我们的图纸(类)
class Robot 
{
    public void Work() { Console.WriteLine("机器人开始工作:滴滴滴..."); }
}

class Program 
{
    static void Main() 
    {
        // 1. 获取图纸(在实际开发中,这个类型可以通过读取文本或配置文件得到)
        Type blueprint = typeof(Robot); 
        
        // 2. 启动 3D 打印机!传入图纸,它就会帮我们造出一个真实的物品
        // Activator.CreateInstance 就是那台神奇的 3D 打印机
        object obj = Activator.CreateInstance(blueprint);
        
        // 3. 验证一下,把打印出来的物品当做机器人来使用
        Robot myRobot = (Robot)obj;
        myRobot.Work(); // 输出:机器人开始工作:滴滴滴...
    }
}

3. 获取类的所有成员列表

简单代码示例:

csharp 复制代码
using System;
using System.Reflection;

// 这是一个普通的英雄类
class Hero 
{
    // 这是一个公共方法(英雄的技能)
    public void Attack(string targetName, int damage) 
    {
        Console.WriteLine($"英雄拔出大剑,对【{targetName}】造成了 {damage} 点真实伤害!");
    }
}

class Program 
{
    static void Main() 
    {
        // 1. 拿到英雄的"设计图"
        Type heroType = typeof(Hero);
        
        // 2. 开启透视眼,找到名为 "Attack" 的【技能说明书】(MethodInfo)
        MethodInfo attackSkill = heroType.GetMethod("Attack");

        // ---------------- 关键分水岭 ----------------

        // 3. 召唤一个具体的英雄(实例化对象:施法者)
        // 就像你不能指着空气让它放技能,你得先有个实体人物
        object myHero = Activator.CreateInstance(heroType); 
        
        // 4. 准备技能所需的材料(准备参数:目标是谁?伤害多少?)
        // 必须按说明书的要求,把参数打包成一个 object[] 数组(包裹)
        object[] skillParams = new object[] { "史莱姆国王", 9999 };
        
        // 5. 大喊咒语:Invoke!发动技能!
        // 语法:技能说明书.Invoke(谁去放技能, 技能的参数包裹)
        attackSkill.Invoke(myHero, skillParams);
    }
}
相关推荐
向上的车轮2 小时前
熟悉C#如何转TypeScript?
开发语言·typescript·c#
wumingqilin2 小时前
QT 防抖和 节流处理
开发语言·qt
Mem0rin2 小时前
[Java/数据结构]顺序表之ArrayList
java·开发语言·数据结构
9稳2 小时前
基于PLC的生产线自动升降机设计
开发语言·网络·数据库·嵌入式硬件·plc
我是唐青枫2 小时前
C#.NET ReaderWriterLockSlim 深入解析:读写锁原理、升级锁与使用边界
开发语言·c#·.net
4ever.ov02 小时前
定时器/时间轮
开发语言·c++·c·muduo·llinux
编程之升级打怪2 小时前
用排他锁来实现Python语言的变量值更新
开发语言·python
rrrjqy2 小时前
Java基础篇(二)
java·开发语言