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