C#反射(一)

C#反射(一)

 

    在还不太熟悉反射的昨天,以为反射很神秘,在网上到处找答案.今天找了段代码敲了一下,茅塞顿开!其实反射也就那么简单的一回事!
    反射是一种机制,通过这种机制我们可以知道一个未知类型的类型信息.比如,有一个对象a,这个对象不是我们定义的,也许是通过网络捕捉到的,也许是使用泛型定义的,但我们想知道这个对象的类型信息,想知道这个对象有哪些方法或者属性什么的.甚至我们想进一步调用这个对象的方法.关键是现在我们只知道它是一个对象,不知道它的类型,自然不会知道它有哪些方法等信息.这时我们该怎么办?反射机制就是解决这么一个问题的.通过反射机制我们可以知道未知类型对象的类型信息.
  再比如,我们有一个dll文件,我们想调用里面的类.现在假设这个dll文件的类的定义,数量等不是固定的,是经常变化的.也许某一天你要在这个dll里面增加一个类定义.也许你觉得这没什么问题,现在关键是我们在另一个程序集里面要调用这个dll,这是我们的程序必须能够适应这个dll的变化,也就是说即使改变了dll文件的定义也不需要改变我们的程序集.这时候我们就会使用一个未知dll.我们该怎么办?同样,反射机制帮助了我们,我们可以通过反射来实现.
  说白了,反射就是能知道我们未知类型的类型信息这么一个东西.没什么神秘可讲!

  今天我先讲一个获得程序集信息的例子.
  下面我们来举一个例子.例子的思路是这样的:我们有一个dll.该dll里面有许多关于运动的类.每一个类记录了一种体育运动的信息.我们在另外一个程序里面要知道这个dll的信息:(如果你还不能明白我的意思,请耐心的照我的步骤把这个过程走一变!)
  第一步:我们建一个文件Sport.cs.内容如下:
  using System;
  
public abstract class Sport
  {
     protected string name;
     public abstract string GetDuration();
     public abstract string GetName();
  }
  咱们用命令"csc /t:library Sport.cs"编译它.
  第二步,我们再建一个名为SomeSports.cs的文件,内容如下:
using System;
public class Football:Sport
{
   public Football()
   {
      name = "Football";
   }
   public override string GetDuration()
   {
      return "four 15 minute quarters";
   }
   
   public override string GetName()
   {
      return name;
   }
}


public class Hockey:Sport
{
   public Hockey()
   {
       name = "Hockey";
   }
   public override string GetDuration()
   {
       return "three 20 minute periods";
   }
   public override string GetName()
   {
       return name;
   }
}

public class Soccer:Sport
{
   public Soccer()
   {
       name = "Soccer";
   }
   public override string GetDuration()
   {
       return "two 45 minute halves";
   }
   public override string GetName()
   {
       return name;
   }
}

  下面我们用命令"csc /t:library /r:Sport.dll SomeSports.cs"编译该文件.
  现在我们有了我们的运动信息dll文件.现在我们想通过程序知道里面有哪些类.请进入最后一步:
第三步:我们创建文件AssemblyDemo.cs".内容如下:

 

 

using System;
using System.Reflection;

public class AssemblyDemo
{
     public static void Main(string[] args)
     {
         int i,j;
          //==========================
          //First the command line arguments are evaluated.if there isn't
          //at least one,a usage message is printed
          //=================================
          if(args.GetLength(0)<1)
          {
              Console.WriteLine("usage is AssemblyDemo<library_name>");
          }
          else
          {
          //========================

          // An Assembly object is obtained from the command line argument
          //========================

          Assembly assembly=Assembly.LoadFrom(args[0]);
         

          Type[] types=assembly.GetTypes();
          Console.WriteLine(assembly.GetName().Name+"contains the following types");
     
          for(i=0;i<types.GetLength(0);++i)
           {
              Console.WriteLine("\r("+i+")  " + types[i].Name);
           }
          i=types.Length - 1;
          Console.Write("make selection(0-"+i+");");

          j=Convert.ToInt32(Console.ReadLine());
          Console.WriteLine();

               if(types[j].IsSubclassOf(typeof(Sport)))
               {
                  ConstructorInfo ci=types[j].GetConstructor(new Type[0]);
                  Sport sport=(Sport)ci.Invoke(new Object[0]);
                
                  Console.WriteLine(sport.GetName() + "has" + sport.GetDuration());
               }
               else
               {
                  Console.WriteLine(types[j].Name + "is not a sub-class of Sport");
               }
          }
     }
}

}

咱们用命令"csc /r:Sport.dll AssemblyDemo.cs"编译该文件.
下面我们用"AssemblyDemo SomeSports.dll"运行该程序.

进一步程序要求我们输入选项,咱们输入1,就显示了结果:Hockeyhasthree 20 minute periods.

好了,今天就到这里了,下面我将进一步说明如何用反射机制访问对象的类型信息.

posted @ 2012-03-22 20:46  欢喜王子  阅读(237)  评论(0编辑  收藏  举报