最近开始写博客了,这是第一篇。
主要讲述最近看的一些资料的关于反射的应用。
反射指程序可以访问、检测、修改它本身状态行为的一种能力。通过反射可以获得在运行时的.net中每个类型的成员,包括委托、结构、类、枚举。获得了这些信息,便可以创建相应的对象。
反射中最重要的是三个类,当然还有其他的,但一般最主要就这三个
- Assembly:加载和操作程序集。
- Type:得到一个类的类型信息然后还可以反射一个对象出来。
- 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 });
}
}
}