C# Reflection 反射 入门
在C#的using System.Reflection 中有反射这样一个东西。
它可以获取一个程序集中命名空间,类,类成员的信息,就算是private的成员也会暴露出来(赤裸裸的~)。并且反射还可以使我们动态绑定对象(?应该是这样称呼),使得程序灵活性更大。 还可以结合工厂模式进行反射工厂模式的设计(这个是我一直想学习的,可以应用于游戏中的物品创建,技能创建)。
好,讲了这么多,开始说反射。
首先,反射有一个核心就是Type。们知道类存储着我们定义的模板的信息,但是type属于更上一层的,它存储着类的信息。虽然本质上它也是类啦。
如何获取Type呢,我列举了几种方法。
Person p1 = new Person();
Type t = p1.GetType();
Type t1 = Type.GetType("Person");
Type t2 = typeof(Person);
好现在有了Type,那么该引出反射的其他对象了。
Type对象里面有很多方法,主要是Get开头的,如GetMembers,可以获取很多类的信息。还有一些Is开头的,也可以获取很多类的信息。如IsSubClassOf(),用来判断是否是一个类的子类。
现在有四个对象。分别是Assembly(程序集),Module(模块,就是C#中的命名空间),Type(刚讲的),Member(类的成员,包括:字段,构造函数,方法,属性等)。他们的包含关系是左边最大,依次减小。
这些信息我们都可以获得,并且他们相互找到。
Person p1 = new Person();
Type t = p1.GetType();
Assembly ass = t.Assembly;
Module mo = t.Module;
MemberInfo[] ms = t.GetMembers();
对于程序集,有这么些方法可以得到
Assembly ass1 = Assembly.Load("AssemblyName");
Assembly ass2 = typeof(Person).Assembly;
Assembly ass3 = typeof(Person).Module.Assembly;
对于模块也有一些类似的方式可以得到。我就不列举了。
关于探索如何利用反射来获取程序集中某个类的信息,可以参考我另一篇博文
https://mp.csdn.net/postedit/82353085
好,下面讲一下如何动态创建对象。我现在只知道一个类的名字,我想创建这个类的对象,我就可以动态创建。
这个在游戏的技能和物体设计很重要。对于一个武器,我只要知道一个武器类的名字,并且还有一些参数,那么我就可以创建一个武器对象。
Type t = Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
DataTable table = (DataTable)Activator.CreateInstance(t);
还可以根据参数和构造函数创建对象
namespace TestSpace
{
public class TestClass
{
private string _value;
public TestClass(string value)
{
_value=value;
}
}
}
…
Type t = Type.GetType(“TestSpace.TestClass”);
Object[] constructParms = new object[] {“hello”}; //构造器参数
TestClass obj = (TestClass)Activator.CreateInstance(t,constructParms);
…
还可以动态调用方法
namespace TestSpace
{
public class TestClass
{
private string _value;
public TestClass(string value)
{
_value=value;
}
}
}
…
Type t = Type.GetType(“TestSpace.TestClass”);
Object[] constructParms = new object[] {“hello”}; //构造器参数
TestClass obj = (TestClass)Activator.CreateInstance(t,constructParms);
…
总结一下,C#使用反射创建对象最后还是有一步强制转换(TestClass),我无法绕过这一步而仅仅通过一个string的类名创建指定类型的对象。但是我在这一步可以不强制转换,就将这个对象当做一个Object存放在内存,但他实际上是我TestClass的类型,所以对于这个对象,我可以在之后的使用中再强制转化成TestClass。
具体的东西可以参考
上一篇: 使用java反射,获取类的私有属性,调用类的私有方法
下一篇: C# 反射(Reflection)