欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C# Reflection 反射 入门

程序员文章站 2024-01-20 22:27:40
...

在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。

具体的东西可以参考

https://www.cnblogs.com/wangshenhe/p/3256657.html