C#反射讲解 相当易懂.docx
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文件现在我们想通过程序知道里面有哪些类请进入最后一步: 第三步:我们创建文件AssemblyDemocs.内容如下: 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(args0); 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+") " + typesi.Name); i=types.Length - 1; Console.Write("make selection(0-"+i+");"); j=Convert.ToInt32(Console.ReadLine); Console.WriteLine; if(typesj.IsSubclassOf(typeof(Sport) ConstructorInfo ci=typesj.GetConstructor(new Type0); Sport sport=(Sport)ci.Invoke(new Object0); Console.WriteLine(sport.GetName + "has" + sport.GetDuration); else Console.WriteLine(typesj.Name + "is not a sub-class of Sport"); 咱们用命令csc /r:Sport.dll AssemblyDemo.cs编译该文件 下面我们用ssemblyDemo SomeSports.dll运行该程序 进一步程序要求我们输入选项,咱们输入,就显示了结果:ockeyhasthree 20 minute periods. 好了,今天就到这里了,下面我将进一步说明如何用反射机制访问对象的类型信息 我不想在这里过多的描述反射的概念。我还是用我自己觉得最简单、最直接的语言来描述反射“反射就是一种机制,通过这种机制,我们能知道一些位知程序集的详细信息!”;通过上一篇我们已经学会如何得到一个未知程序集的相关信息,接下来我要讲的是如何知道未知程序模块的信息: 模块信息是通过Module类访问的。下面通过一个类子,讲解下Module类的使用,如果你是一个用心的程序员,应该了解下Module的详细信息。 下面我们写一个新的文件ModuleDemo.cs。内容如下: /编译命令 csc /r:Sport.dll ModuleDemo.cs using System; using System.Reflection; public class ModuleDemo public static void Main(string args) /= / Am Module object is obtained representing the / SomeSports.dll library file /= Assembly assembly = Assembly.Load("SomeSports"); Module module = assembly.GetModule("SomeSports.dll"); /= /Search the module for the type named "Football" Type types = module.FindTypes(Module.FilterTypeName,"Football"); if(types.Length != 0) ConstructorInfo ci = types0.GetConstructor(new Type0); Sport sport = (Sport)ci.Invoke(new Object0); Console.WriteLine(sport.GetName + " has "+sport.GetDuration); else Console.WriteLine("type not found"); 我们用csc /r:Sport.dll ModuleDemo.cs编译,然后用MouduleDemo运行程序就能看到如下输出:Football has four 15 minute quarters。 关于C#反射的基础知识,还有一个知识点就是访问未知对象的类型信息。在下一篇我将介绍它,并介绍我自己曾经写过的一个应用,可以实现具有相同属性或域名的不同类型对象之间的数据相互复制