C# 学习笔记:反射

本文介绍了C#反射的基本概念及其实现方式,通过创建和调用动态链接库中的类和方法,展示了反射如何帮助代码实现更高程度的解耦合和灵活性。文中详细解释了Assembly、Type和MethodInfo三个核心类的使用,并提供了实例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近开始写博客了,这是第一篇。

主要讲述最近看的一些资料的关于反射的应用。

反射指程序可以访问检测修改它本身状态行为的一种能力。通过反射可以获得在运行时的.net中每个类型的成员,包括委托、结构、类、枚举。获得了这些信息,便可以创建相应的对象。

反射中最重要的是三个类,当然还有其他的,但一般最主要就这三个

  1. Assembly:加载和操作程序集。
  2. Type:得到一个类的类型信息然后还可以反射一个对象出来。
  3. MethodInfo:获得方法的信息。

例子:

我们创建两个类,一个叫打游戏,一个叫冲冲冲,它们里面都很简单:

第一个类就是说玩游戏啥的

    public class Game1
    {
        private string GameName;
        public Game1(string gamename)
        {
            GameName = gamename;
        }
        public void Shout()
        {
            if (GameName != null)
            {
                Console.WriteLine(GameName + "真好玩");
            }
            else
            {
                Console.WriteLine("没游戏玩个啥");
            }
        }
    }

第二个类就是发出“冲冲冲”的呐喊

    class Game2
    {
        public void Rush(int Times)
        {
            for(int i=0;i<Times;i++)
            {
                Console.WriteLine("冲");
            }
        }
    }

然后把它生成解决方案,获得它的动态链接库

然后我们把这个放入我们要获得这个库的debug文件夹里

然后就可以在代码中调用了:

            Type Game1 = null;
            Type Game2 = null;
            Assembly a = Assembly.LoadFrom("Games.dll");
            //1.获得相应的dll文件
            Type[] types = a.GetTypes();
            //2.获得文件中的类型集合
            foreach(Type t in types)
            {//遍历得到我们想要的类
                if(t.Name=="Game1")
                {
                    Console.WriteLine("找到了Game1");
                    Game1 = t;
                }
                if (t.Name == "Game2")
                {
                    Console.WriteLine("找到了Game2");
                    Game2 = t;
                }
            }
            MethodInfo[] info1 = Game1.GetMethods();
            foreach(MethodInfo i in info1)
            {
                Console.WriteLine(i.Name);
            }
            MethodInfo[] info2 = Game2.GetMethods();
            foreach (MethodInfo i in info2)
            {
                Console.WriteLine(i.Name);
            }

首先我们先遍历一遍Type类型,找到我们想要的,然后我们先测试一下,看看里面的函数是不是我刚刚定义的

正如我们想象的一样,就是我们定义的那些,其他的是继承自Object类的方法,一并被输出出来了。

然后我们就可以创建类的实例了,这里要调用Activator下的CreatInstance方法,和Unity中的Instantiate方法很像:

​
            Object g1 = Activator.CreateInstance(Game1,"彩虹六号");
            //创建我们的类的实例,注意如果构造函数有参数要传入
            MethodInfo infoObj1 = Game1.GetMethod("Shout");
            //调用类中的方法,这里要先用MethodInfo获得这个类的信息。
            infoObj1.Invoke(g1, null);
            //调用类的方法,由于不是静态的类,我们需要告诉代码是哪个实例在调这个类,后面跟的null表示没有形参
​

然后我们就可以看到这个函数的调用情况了:

是的,彩虹六号真好玩,说明我们已经调用成功。

然后我们再来看看第二个类的调用,第二个类没有指定构造器,但是函数有形参

            Object g2 = Activator.CreateInstance(Game2);
            //没有形参,直接创建就行
            MethodInfo infoObj2 = Game2.GetMethod("Rush");
            //创建函数信息的实例

            Console.WriteLine("输入你需要的数字");
            int Times = int.Parse(Console.ReadLine());
            //这里我们需要来指定一下形参的数字

            infoObj2.Invoke(g2, new Object[] { Times });
            //调用,注意形参是Object数组的形式

然后我们的结果是:

冲冲冲,代码替我们发出了呐喊。

总结:

以上只是反射最最最基础的用法,它进一步解耦合,实现了依赖注入,这样我们即使不知道一个类中的字段和成员,也可以生成它们的实例,我们甚至不需要知道它们的类型,这样的话代码的灵活程度就更进了一步。

这里只是简单的配上了类来使用,如果是接口,我们可以创建接口的对象指向实现接口的类的实例(依赖反转)的方式,来使灵活度进一步提升(这样的方法在插件中使用的比较多)。

备注:我是初学者,大家看到有错误就可以指出来哈,还有,感谢刘铁猛老师的教程,讲的真的很好。

    class Program
    {
        static void Main(string[] args)
        {
            Type Game1=null;
            Type Game2 = null;
            Assembly getAssembly = Assembly.LoadFrom("Games.dll");

            Type[] Game = getAssembly.GetTypes();

            foreach(Type type in Game)
            {
                if (type.Name == "Game1") 
                {
                    Console.WriteLine("找到了Game1");
                    Game1 = type;
                }
            }
            if(Game1!=null)
            {
                MethodInfo definition = Game1.GetMethod("Shout");

                object getGenericInstance = Activator.CreateInstance(Game1);

                MethodInfo getGenericMethod = definition.MakeGenericMethod(typeof(string));

                string a = "haha";

                getGenericMethod.Invoke(getGenericInstance, new object[] { a });
            }
        }
    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值