09.C#反射机制

1.反射机制基础类

(1)反射机制的功能与介绍

审查元数据并收集关于它的类型信息的能力称为反射。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。System.reflection命名空间包含的几个类,允许用户解析这些元数据表的代码:

System.Reflection.Assembly:         表示一个程序集。

System.Reflection.Module:           在模块上执行反射。

System.Type:                        表示各种类型。

System.Reflection.MethodBase:       提供有关方法和构造函数的信息。

System.Reflection.MethodInfo:       发现方法的属性并提供对方法元数据的访问。

System.Reflection.MemberInfo:       获取或访问有关成员属性。

System.Reflection.FieldInfo:        发现字段属性并提供对字段元数据的访问权。

System.Reflection.PropertyInfo:     发现或访问属性(Property)的属性(Attribute)。

System.Reflection.EventInfo:        发现事件的属性并提供对事件元数据的访问权。

System.Reflection.ConstructorInfo:  发现或访问类构造函数的属性。

(2)反射层次模型图

(3)Assembly类获取程序及信息

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Assembly assem = Assembly.Load("mscorlib");//加载系统程序集
  6. PrintInfo(assem);//输出程序集相关信息
  7. assem = Assembly.LoadFrom(@"F:\System.Data.SQLite.dll");//或使用LoadFile()方法
  8. PrintInfo(assem);//输出程序集相关信息
  9. assem = Assembly.GetExecutingAssembly();//获取当前执行代码的程序集
  10. PrintInfo(assem);//输出程序集相关信息
  11. Console.Read();
  12. }
  13. //输出程序集相关信息
  14. static void PrintInfo(Assembly assem)
  15. {
  16. Console.WriteLine("程序集全名:" + assem.FullName);
  17. Console.WriteLine("程序集的版本:" + assem.GetName().Version);
  18. Console.WriteLine("程序集初始位置:" + assem.CodeBase);
  19. Console.WriteLine("程序集位置:" + assem.Location);
  20. Console.WriteLine("程序集入口:" + assem.EntryPoint);
  21. Type[] types = assem.GetTypes();//得到该程序集里所有的类型
  22. Console.WriteLine("程序集下包含的类型数:" + types.Length);
  23. //foreach (var item in types)
  24. //{
  25. // Console.WriteLine("类:" + item.Name);//输出类型名
  26. //}
  27. Console.WriteLine("============================\n");
  28. }
  29. }

(4)Module类获取程序集模块信息

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Assembly assembly = Assembly.Load("mscorlib");//加载程序集
  6. Module module = assembly.GetModule("CommonLanguageRuntimeLibrary");//得到指定模块
  7. Console.WriteLine("模块名:"+module.Name);
  8. Type[] types = module.FindTypes(Module.FilterTypeName, "Assembly*");
  9. foreach (var item in types)
  10. {
  11. Console.WriteLine("类名:" + item.Name);//输出类型名
  12. }
  13. Console.Read();
  14. }
  15. }

(5)Type类获取类型的信息

  1. class Myclass
  2. {
  3. private int Id;
  4. public string Name;
  5. public void Method(int i) { }
  6. }
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. Type type = typeof(Myclass);
  12. Console.WriteLine("类型名:" + type.Name);
  13. Console.WriteLine("类全名:" + type.FullName);
  14. Console.WriteLine("命名空间名:" + type.Namespace);
  15. Console.WriteLine("程序集名:" + type.Assembly);
  16. Console.WriteLine("模块名:" + type.Module);
  17. Console.WriteLine("基类名:" + type.BaseType);
  18. Console.WriteLine("是否类:" + type.IsClass);
  19. Console.WriteLine("类的公共成员:");
  20. MemberInfo[] memberInfos = type.GetMembers();//得到所有公共成员
  21. foreach (var item in memberInfos)
  22. {
  23. Console.WriteLine("成员类型:" + item.MemberType + "\t成员:" + item);
  24. }
  25. Console.Read();
  26. }
  27. }

(6)利用反射调用方法

  1. class Myclass
  2. {
  3. public Myclass()
  4. {
  5. Console.WriteLine("创建Myclass对象!");
  6. }
  7. public void Method(int i)
  8. {
  9. Console.WriteLine("输出值:" + i);
  10. }
  11. }
  12. class Program
  13. {
  14. static void Main(string[] args)
  15. {
  16. Type t = typeof(Myclass);//得到类型
  17. object o = Activator.CreateInstance(t);//创建类型的实例
  18. Console.WriteLine("已创建Myclass对象:" + o);
  19. MethodInfo method = t.GetMethod("Method");//获得实例的方法
  20. method.Invoke(o, new object[] { 100 });//调用方法
  21. Console.Read();
  22. }
  23. }

2.特性(Attribute)

(1)Attribute介绍

Attributes是一种新的描述信息,我们既可以使用attributes来定义设计信息(例如:帮助文件,文档的URL),还可以用attributes定义运行时信息(例如,使XML中的元素与类的成员字段关联起来)。我们也可以用attributes来创建一个“自描述”的组件。

(2)示例

  1. class Program
  2. {
  3. [Obsolete("已过时的方法!", true)]//把true改成false就可以编译通过
  4. static void OldMethod() { }
  5. static void Main(string[] args)
  6. {
  7. OldMethod();//调用过时的方法
  8. Console.Read();
  9. }
  10. }

在该实例中我们用到了“Obsolete”Attribute,它标记了一个不该再被使用的语言元素(这里的元素为方法),该属性的第一个参数是string类型,它解释为什么该元素被荒弃,以及我们该使用什么元素来代替它。实际中,我们可以书写任何其它文本来代替这段文本。第二个参数是告诉编译器把依然使用这被标识的元素视为一种错误,这就意味着编译器会因此而产生一个警告。

3.自定义特性

(1)自定义特性说明

自定义的Attribute类都派生于System.Attribute类。

(2)示例

  1. //自定义的Attribute类命名为XXXAttribute
  2. class HelpAttribute : Attribute
  3. {
  4. private String description;
  5. public HelpAttribute(String Descrition_in)
  6. {
  7. this.description = Descrition_in;
  8. }
  9. public String Description
  10. {
  11. get { return description; }
  12. }
  13. }
  14. class Program
  15. {
  16. [Help("自定义特性")]//使用是不需要写“Attribute”后缀
  17. static void Main(string[] args)
  18. {
  19. Console.Read();
  20. }
  21. }

注意:按惯例我们是用”Attribute“作为attribute类名的后缀,然而,当我们当我们把attribute绑定到某语言元素时,是不包含“Attribute“后缀的。编译器首先在System.Attribute 的继承类中查找该attribute,如果没有找到,编译器会把“Attribute“追加到该attribute的名字后面,然后查找它。

(3)AttributeUsage类的使用

AttributeUsage类是另一预定义类(Attribute类本身用System.AttributeUsage类来标记),它将帮助我们控制我们自定义Attribute类的用法,这就是,我们能为自定义的Attribute类定义Attributes属性。它描述了一个自定义Attribute类能被怎样使用。

AttributeUsage提供三个属性,我们能将它们放置到我们的自定义Attribute类上。

AllowMultiple属性:该值指示能否为一个程序元素指定多个指示属性实例。

Inherited属性:该值指示指示的属性能否由派生类和重写成员继承。

ValidOn属性:获取一组值,这组值标识指示的属性可应用到的程序元素。

此属性是AttributeTargets类型的枚举,可取如下值:

使用示例:

  1. [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
  2. class HelpAttribute : Attribute
  3. {
  4. private String description;
  5. public HelpAttribute(String Descrition_in)
  6. {
  7. this.description = Descrition_in;
  8. }
  9. public String Description
  10. {
  11. get { return description; }
  12. }
  13. }
  14. class Program
  15. {
  16. [Help("自定义特性")]
  17. static void Main(string[] args)
  18. {
  19. Console.Read();
  20. }
  21. }

(4)可选参数与命名参数

可选参数是Attribute类构造函数的参数。它是强制的,必须在每次在Attribute绑定至某语言元素时提供一个值。而另一方面,命名参数倒是真正的可选参数,不是在Attribute构造函数的参数。

  1. [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
  2. class HelpAttribute : Attribute
  3. {
  4. private string _description;//可选参数
  5. public string _name;//命名参数
  6. public HelpAttribute(string description)
  7. {
  8. Console.WriteLine("HelpAttribute特性被创建!");
  9. this._description = description;
  10. }
  11. public string Description
  12. {
  13. get { return _description; }
  14. }
  15. public string Name
  16. {
  17. get { return _name; }
  18. set//命名参数,必须要有set方法
  19. {
  20. Console.WriteLine("属性:" + value);
  21. _name = value;
  22. }
  23. }
  24. }
  25. class Program
  26. {
  27. [Help("自定义特性", Name = "李志伟")]//同时使用可选参数与命名参数
  28. static void Main(string[] args)
  29. {
  30. Console.Read();
  31. }
  32. }

(5)Attributes标识符

假设,我们想把HelpAttribute绑定到整个assembly(程序集)。第一个问题是我们要把HelpAttribute放在哪儿才能让编译器确定该Attribute是绑定至整个assembly呢?考虑另一种情况,我们想把Attribute绑定至一个方法的返回类型上,怎样才能让编译器确定我们是把Attribute绑定至方法的返回类型上,而不是整个方法呢?

为了解决诸如此类的含糊问题,我们使用Attribute标识符,有了它的帮助,我们就可以确切地申明我们把attribute 绑定至哪一个语言元素。例如:[assembly: Help("类上的自定义特性", Name = "lizhiwei")]这个在HelpAttribute前的assembly标识符确切地告诉编译器,该Attribute被绑定至整个assembly(程序集)。可能的标识符有:assembly、module、type、method、property、event、field、param、return。

(6)通过反射获取Attributes

  1. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
  2. class HelpAttribute : Attribute
  3. {
  4. private string _description;//可选参数
  5. private string _name;//命名参数
  6. public HelpAttribute(string description)
  7. {
  8. Console.WriteLine("====HelpAttribute特性被创建!====");
  9. this._description = description;
  10. }
  11. public string Description
  12. {
  13. get { return _description; }
  14. }
  15. public string Name
  16. {
  17. get { return _name; }
  18. set//命名参数,必须要有set方法
  19. {
  20. Console.WriteLine("====属性:" + value + "====");
  21. _name = value;
  22. }
  23. }
  24. }
  25. //使用了自定义特性的测试类
  26. [Help("类上的自定义特性", Name = "lizhiwei")]
  27. class TestClass
  28. {
  29. [Help("方法上的自定义特性", Name = "李志伟1")]
  30. [Help("方法上的自定义特性", Name = "李志伟2")]
  31. public void TestMethod()
  32. {
  33. Console.WriteLine("===========测试方法===========");
  34. }
  35. }
  36. class Program
  37. {
  38. static void Main(string[] args)
  39. {
  40. Type t = typeof(TestClass);
  41. //获取类上的自定义特性
  42. object[] obis = t.GetCustomAttributes(typeof(HelpAttribute), false);
  43. HelpAttribute attribute = obis[0] as HelpAttribute;
  44. Console.WriteLine("\n" + attribute.Description + "--" + attribute.Name + "\n");
  45. //获取方法上的自定义特性
  46. MethodInfo method = t.GetMethod("TestMethod");
  47. object[] methods = method.GetCustomAttributes(typeof(HelpAttribute), false);
  48. foreach (HelpAttribute help in methods)
  49. {
  50. Console.WriteLine("\n" + help.Description + "--" + help.Name + "\n");
  51. }
  52. Console.Read();
  53. }
  54. }

-------------------------------------------------------------------------------------------------------------------------------

来自为知笔记(Wiz)

时间: 2024-10-12 21:27:25

09.C#反射机制的相关文章

Java系列笔记(2) - Java RTTI和反射机制

目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这就是RTTI(Runtime Type Information,运行时类型信息). 在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型:还有一种,是利用反射机制,在运行时再尝试确定类型信息. 本文主要讲反射方式实现的RTTI,建议在阅读本文之前,先了解类的加载机制(

Java反射机制及IoC原理

一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 类中有什么信息,利用反射机制就能可以获得什么信息,不过前提是得知道类的名字. 二. 反射机制的作用 在运行时判断任意

Java知识总结:Java反射机制(用实例理解)

概念理解: 反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. Java中的反射是一个强大的工具,他能够创建灵活的代码,这些 代码可以在运行时装配,无需在组件之间进行链接,发射允许在编写和执行时,使程序代码能够接入装载到 JVM 中的类的内部信息 .而不是源代码中选定的类协作的代码.这使发射

初探Java反射机制

反射库提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵java代码的程序库.这项功能被大量地应用于JavaBeans中.反射机制提供了在运行状态中获得和调用修改任何一个类的属性和方法的能力. Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理. 首先让我们来看一个简单的小程序,感性的认识一下Java反射机制: 1 import java.lang

JAVA反射机制及应用场景

JAVA反射机制: http://www.programcreek.com/2013/09/java-reflection-tutorial/ 关于JAVA反射机制打破数据封装的问题的解释: http://stackoverflow.com/questions/16635025/dosent-reflection-api-break-the-very-purpose-of-data-encapsulation JAVA反射机制运用场景: 1.对于J2EE来说,Hibernate之类的ORM全都基

【Object C】 反射机制

Object-C 也提供了类似Java的反射机制.通过以下三种方式与运行环境交互: 1.直接通过Object-C源代码 2.通过NSObject中定义的方法: isKindOfClass isMemberOfClass responseToSelector:判断该实例是否调用指定方法 3.直接调用运行时函数进行动态编程 #import <Foundation/Foundation.h> #import "DCApple.h" int main(int argc, const

利用java反射机制 读取配置文件 实现动态类加载以及动态类型转换

作者:54dabang 在spring的学习过程之中,我们可以看出通过配置文件来动态管理bean对象的好处(松耦合 可以让零散部分组成一个整体,而这些整体并不在意之间彼此的细节,从而达到了真正的物理上的疏散耦合,而非逻辑,有了IOC之后,我们可以让SPRING充当各框架中的整合器,把技术框架进行完美的结合). Spring实现的一个重要的机制是通过反射(java.lang.reflect)读取配置文件,通过配置文件来动态生成配置文件中的类对象.Java动态加载类主要是为了不改变主程序代码,通过修

Android小例子:使用反射机制来读取图片制作一个图片浏览器

效果图: 工程文件夹: 该例子可供于新手参考练习,如果有哪里不对的地方,望指正>-< <黑幕下的人> java代码(MainActivity.java): package com.example.imageswitchtest; import java.lang.reflect.Field; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.v

java反射机制(一)—— 利用反射机制实例化对象

一.Java有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载.探知.使用编译期间完全未知的classes.换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体.或对其fields设值.或唤起其methods.(度娘文库是这么说的) 二.这篇文章主要介绍一下通过反射机制去实例化一个类的对象,然后调用其方法.本文主要介绍两种方式,第一种就是通过构造函数来实例化,第二种就是通过Cl