你应该知道的c# 反射详解

C#反射

首先了解C#反射的概念,反射是一个运行库类型发现的过程。通过反射可以得到一个给定程序集所包含的所有类型的列表, 这个列表包括给定类型中定义的方法、字段、属性和事件。也可以动态的发现一组给定类支持的借口、方法的参数和其他 相关信息如基类、命名空间、数据清单等。

C#反射命名空间详细介绍:

1.System.Reflection命名空间内的各类型

(1) Assembly通过它可以加载、了解和操纵一个程序集

(2) AssemblyName 通过它可以找到大量隐藏在程序集的身份中的信息,如版本信息、区域信息等

(3) EventInfo 事件的信息

(4) FieldInfo 字段的信息

(5) MethodInfo 方法的信息

(6) ParameterInfo 参数的信息

(7) PropertyInfo 属性的信息

(8) MemberInfo 是抽象基类,为 EventInfo、FieldInfo 、MethodInfo、PropertyInfo等类型定义了公共的行为。

(9) Module 用来访问带有多文件程序集的给定模块

2.System.Type类

System.Type支持的成员可以分为这样几类

(1) Is***   用来检查一个类型的元数据,如IsAbstract、IsClass、IsValueType等等

(2) Get*** 用来从类型得到指定项目,如GetEvent()得到类型的一个指定的事件(EventInfo)。  另外,这些方法都有一个单数版本和一个复数版本。如GetEvent()对应有一个复数版本GetEvents(), 该方法返回一个相关的EventInfo数组。

(3) FindMembers()   根据查询条件返回一个MemberInfo类型的数组

(4)GetType() 该静态方法根据一个字符串名称返回一个Type实例

(5)InvokeMember() 对给定项目进行晚期绑定

3.得到一个Type类型实例的三种方法

因为Type是一个抽象类,所以不能直接使用new关键字创建一个Type对象

(1)使用System.Object.GetType()

Person pe=new Person();    //---------定义pe为person类的一个对象    Type t=pe.GetType();

(2)使用System.Type.GetType()静态方法,参数为类型的完全限定名

Type t=Type.GetType("Entity.Person"); 该方法被重载,允许指定两个布尔类型的参数,一个用来控制当前类型不能找到时是否抛出异常,

另一个用来指示是否区分字符串大小写

Type t=Type.GetType("Entity.Person",false,true); 注意到传入的字符串并没有包含类型所在的程序集信息,此时该类型便被认为是定义在当前执行的程序集中的。

要得到一个外部私有程序集的类型元数据时,字符串参数必须使用类型完全限定名加上类型所在程序集的友好名字

Type t=Type.GetType("Entity.Person","Entity"); //------"Entity"即为类型所在程序集的友好名字 嵌套类型:传入的字符串可以指定一个+标记来表示一个嵌套类型,

如希望得到一个嵌套在person类中的枚举类型City的类型信息,则可以这样

Type t=Type.GetType("Entity.person+City");

(3)使用typeof运算符

Type t=typeof(person); 三种方法的比较:

使用第一种方法必须先建立一个实例,而后两种方法不必先建立实例。但使用typeof运算符仍然需要知道类型的编译时信息,

而使用System.Type.GetType()静态方法不需要知道类型的编译时信息,所以是首选方法。

一个最简单的C#反射实例,首先编写类库如下: namespace ReflectionTest {     public class WriteTest     {         //带参数的公共方法     public void WriteString(string s, int i)      {         Console.WriteLine("WriteString:" + s + i.ToString());      }        //带一个参数的静态方法     public static void StaticWriteString(string s)     {          Console.WriteLine("StaticWriteString:" + s);      }      //不带参数的静态方法     public static void NoneParaWriteString()      {           Console.WriteLine("NoParaWriteString");      }     }  }

class TestApp {     public static void Main()     {      Assembly ass;      Type type;      Object obj;        //用来测试静态方法     Object any = new Object();        //指定类库文件必须使用绝对路径,不能使用相对路径     ass = Assembly.LoadFile(@"D:\Source Code\00.C#Sudy\01.Reflection\01\ReflectTest.dll");      //命名空间和类的名字必须一起指定      type = ass.GetType("ReflectionTest.WriteTest");           /**//*example1---------*/      MethodInfo method = type.GetMethod("WriteString");        string test = "test";      int i = 1;        Object[] parametors = new Object[]{test,i};        //在例子1种必须实例化反射要反射的类,因为要使用的方法并不是静态方法。     //创建对象实例     obj = ass.CreateInstance("ReflectionTest.WriteTest");          //执行带参数的公共方法     method.Invoke(obj, parametors);      //method.Invoke(any, parametors);//异常:必须实例化反射要反射的类,因为要使用的方法并不是静态方法。          /**//*example2----------*/        method = type.GetMethod("StaticWriteString");      method.Invoke(null, new string[] { "test"}); //第一个参数忽略     //对于第一个参数是无视的,也就是我们写什么都不会被调用,     //即使我们随便new了一个any这样的Object,当然这种写法是不推荐的。     //但是对应在例子1种我们如果Invoke的时候用了类型不一致的实例来做为参数的话,将会导致一个运行时的错误。     method.Invoke(obj, new string[] { "test"});     method.Invoke(any, new string[] { "test"});          /**//*example3-----------*/      method = type.GetMethod("NoneParaWriteString"); //调用无参数静态方法的例子,这时候两个参数我们都不需要指定,用null就可以了。s      method.Invoke(null, null);     }  }

从上面的总结中可以看出,对于外部调用的动态库应用反射时要用到Assembly.LoadFile(),然后才是获取类型、执行方法等; 当用反射创建当前程序集中对象实例或执行某个类下静态方法时只需通过Type.GetType("类的完整名")。

整理2

在还不太熟悉反射的昨天,以为反射很神秘,在网上到处找答案.今天找了段代码敲了一下,茅塞顿开!其实反射也就那么简单的一回事!     反射是一种机制,通过这种机制我们可以知道一个未知类型的类型信息.比如,有一个对象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的文件,内容如下:

C#代码  

  1. using System;
  2. public class Football:Sport
  3. {
  4. public Football()
  5. {
  6. name = "Football";
  7. }
  8. public override string GetDuration()
  9. {
  10. return "four 15 minute quarters";
  11. }
  12. public override string GetName()
  13. {
  14. return name;
  15. }
  16. }
  17. public class Hockey:Sport
  18. {
  19. public Hockey()
  20. {
  21. name = "Hockey";
  22. }
  23. public override string GetDuration()
  24. {
  25. return "three 20 minute periods";
  26. }
  27. public override string GetName()
  28. {
  29. return name;
  30. }
  31. }
  32. public class Soccer:Sport
  33. {
  34. public Soccer()
  35. {
  36. name = "Soccer";
  37. }
  38. public override string GetDuration()
  39. {
  40. return "two 45 minute halves";
  41. }
  42. public override string GetName()
  43. {
  44. return name;
  45. }
  46. }
  47.   下面我们用命令"csc /t:library /r:Sport.dll SomeSports.cs"编译该文件.
  48.   现在我们有了我们的运动信息dll文件.现在我们想通过程序知道里面有哪些类.请进入最后一步:
  49. 第三步:我们创建文件AssemblyDemo.cs".内容如下:
  50. using System;
  51. using System.Reflection;
  52. public class AssemblyDemo
  53. {
  54. public static void Main(string[] args)
  55. {
  56. int i,j;
  57. //==========================
  58. //First the command line arguments are evaluated.if there isn‘t
  59. //at least one,a usage message is printed
  60. //=================================
  61. if(args.GetLength(0)<1)
  62. {
  63. Console.WriteLine("usage is AssemblyDemo<library_name>");
  64. }
  65. else
  66. {
  67. //========================
  68. // An Assembly object is obtained from the command line argument
  69. //========================
  70. Assembly assembly=Assembly.LoadFrom(args[0]);
  71. Type[] types=assembly.GetTypes();
  72. Console.WriteLine(assembly.GetName().Name+"contains the following types");
  73. for(i=0;i<types.GetLength(0);++i)
  74. {
  75. Console.WriteLine("\r("+i+") " + types[i].Name);
  76. }
  77. i=types.Length - 1;
  78. Console.Write("make selection(0-"+i+");");
  79. j=Convert.ToInt32(Console.ReadLine());
  80. Console.WriteLine();
  81. if(types[j].IsSubclassOf(typeof(Sport)))
  82. {
  83. ConstructorInfo ci=types[j].GetConstructor(new Type[0]);
  84. Sport sport=(Sport)ci.Invoke(new Object[0]);
  85. Console.WriteLine(sport.GetName() + "has" + sport.GetDuration());
  86. }
  87. else
  88. {
  89. Console.WriteLine(types[j].Name + "is not a sub-class of Sport");
  90. }
  91. }
  92. }
  93. }
  94. }

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

你应该知道的c# 反射详解

时间: 2024-11-15 18:14:22

你应该知道的c# 反射详解的相关文章

.net反射详解(转)

摘自:http://www.cnblogs.com/knowledgesea/archive/2013/03/02/2935920.html 概述反射 通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象. 反射机制允许程序在执行过程中动态地添加各种功能.  运行时类型标识 运行时类型标识(RTTI),可以在程序执行期间判定对象类型.例如使用它能够确切地知道基类引用指向了什么类型对象. 运行时类型标识,能预先测试某个强制类型转换操作,能否成功,从而避免无效的强制类

java 反射 详解

本文来自:blog.csdn.net/ljphhj JAVA反射机制:   通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没用,下面我们看看实践 Demo - Demo: package cn.lee.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import

Java反射详解

Java反射详解 分类:java, 基础日期:2012-07-20作者:ticmy 19 反射,是Java中非常重要的一个功能,如果没有反射,可以说很多框架都难以实现. 什么是反射?说白了就是可以通过Java代码获取装载到方法区的类信息的手段. 当装载一个类时,会在方法区产生一个数据结构,该结构中包含着装载的类的相关信息.字节码可以看成是数据流,那么方法区的这种数据结构可以说是字节码数据流的结构化表现.装载的最终产物就是java.lang.Class类的一个对象,它是Java程序与方法区内部数据

java反射详解 (转至 http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html)

本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象获得完整的包名和类名 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package Reflect; /**  * 通过一个对象获得完整的包名和类名  * */ class Demo{     //other codes... } class hello{     pu

Java 反射详解 转载

java 反射 定义 功能 示例 概要: Java反射机制详解 | |目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的Arr

学习前端前必知的——HTTP协议详解

前端人士必备的知识点,无论你是否有经验,看了此文绝对有收获 此文针对前端爱好者,前端求职者(话说面试时很容易考到哦) 原文参考博客园http://kb.cnblogs.com/page/130970/#statecode 什么是HTTP协议 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器 目前我们使用的是HTTP/1.1 版本 Web服务器,浏览器,代理服

Java 反射详解

反射反射,程序员的快乐,今天你快乐了吗?如果你不快乐,没关系,接下来让你快乐起来! 一.什么是反射? 通过百度百科我们可以知道,Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性.而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C

.net反射详解 原文://http://blog.csdn.net/wenyan07/article/details/27882363

概述反射 通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象. 反射机制允许程序在执行过程中动态地添加各种功能. 运行时类型标识 运行时类型标识(RTTI),可以在程序执行期间判定对象类型.例如使用它能够确切地知道基类引用指向了什么类型对象. 运行时类型标识,能预先测试某个强制类型转换操作,能否成功,从而避免无效的强制类型转换异常. 在c#中有三个支持RTTI的关键字:is . as  .typeof. 下面依次介绍他们 is运算符: 通过is运算符,能够判断对

第二十四部分_Java反射详解

Java语言的反射机制 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的.这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制. Java反射机制主要提供了以下功能 在运行时判断任意一个对象所属的类. 在运行时构造任意一个类的对象. 在运行时判断任意一个类所具有的成员变量和方法. 在运行时调用任意一个对象的方法. Reflection是Java被视为动态(或准动态)语言