反射

反射(Reflection) 对象用于在运行时获取类型信息。该类位于 System.Reflection 命名空间中,可访问一个正在运行的程序的元数据。

System.Reflection 命名空间包含了允许您获取有关应用程序信息及向应用程序动态添加类型、值和对象的类。

反射的应用

反射(Reflection)有下列用途:

  • 它允许在运行时查看属性(attribute)信息。
  • 它允许审查集合中的各种类型,以及实例化这些类型。
  • 它允许延迟绑定的方法和属性(property)。
  • 它允许在运行时创建新类型,然后使用这些类型执行一些任务。

查看元数据

我们已经在上面的章节中提到过,使用反射(Reflection)可以查看属性(attribute)信息。

System.Reflection 类的 MemberInfo 对象需要被初始化,用于发现与类相关的属性(attribute)。为了做到这点,您可以定义目标类的一个对象,如下:

  1. System.Reflection.MemberInfo info = typeof(MyClass);

下面的程序示范了这点:

  1. using System;
  2. [AttributeUsage(AttributeTargets.All)]
  3. public class HelpAttribute : System.Attribute
  4. {
  5. public readonly string Url;
  6. public string Topic // Topic 是一个表示名字的参数
  7. {
  8. get
  9. {
  10. return topic;
  11. }
  12. set
  13. {
  14. topic = value;
  15. }
  16. }
  17. public HelpAttribute(string url) // url 是一个表示位置的参数
  18. {
  19. this.Url = url;
  20. }
  21. private string topic;
  22. }
  23. [HelpAttribute("Information on the class MyClass")]
  24. class MyClass
  25. {
  26. }
  27. namespace AttributeAppl
  28. {
  29. class Program
  30. {
  31. static void Main(string[] args)
  32. {
  33. System.Reflection.MemberInfo info = typeof(MyClass);
  34. object[] attributes = info.GetCustomAttributes(true);
  35. for (int i = 0; i < attributes.Length; i++)
  36. {
  37. System.Console.WriteLine(attributes[i]);
  38. }
  39. Console.ReadKey();
  40. }
  41. }
  42. }

当上面的代码被编译和执行时,它会显示附加到类 MyClass 上的自定义属性:

  1. HelpAttribute

示例

在本实例中,我们将使用在上一章中创建的 DeBugInfo 属性,并使用反射(Reflection)来读取 Rectangle 类中的元数据。

  1. using System;
  2. using System.Reflection;
  3. namespace BugFixApplication
  4. {
  5. //自定义特性BugFix分配给一个类和他的成员
  6. [AttributeUsage(AttributeTargets.Class |
  7. AttributeTargets.Constructor |
  8. AttributeTargets.Field |
  9. AttributeTargets.Method |
  10. AttributeTargets.Property,
  11. AllowMultiple = true)]
  12. public class DeBugInfo : System.Attribute
  13. {
  14. private int bugNo;
  15. private string developer;
  16. private string lastReview;
  17. public string message;
  18. public DeBugInfo(int bg, string dev, string d)
  19. {
  20. this.bugNo = bg;
  21. this.developer = dev;
  22. this.lastReview = d;
  23. }
  24. public int BugNo
  25. {
  26. get
  27. {
  28. return bugNo;
  29. }
  30. }
  31. public string Developer
  32. {
  33. get
  34. {
  35. return developer;
  36. }
  37. }
  38. public string LastReview
  39. {
  40. get
  41. {
  42. return lastReview;
  43. }
  44. }
  45. public string Message
  46. {
  47. get
  48. {
  49. return message;
  50. }
  51. set
  52. {
  53. message = value;
  54. }
  55. }
  56. }
  57. [DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
  58. [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
  59. class Rectangle
  60. {
  61. //成员变量
  62. protected double length;
  63. protected double width;
  64. public Rectangle(double l, double w)
  65. {
  66. length = l;
  67. width = w;
  68. }
  69. [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
  70. public double GetArea()
  71. {
  72. return length * width;
  73. }
  74. [DeBugInfo(56, "Zara Ali", "19/10/2012")]
  75. public void Display()
  76. {
  77. Console.WriteLine("Length: {0}", length);
  78. Console.WriteLine("Width: {0}", width);
  79. Console.WriteLine("Area: {0}", GetArea());
  80. }
  81. }//Rectangle 类的结束
  82. class ExecuteRectangle
  83. {
  84. static void Main(string[] args)
  85. {
  86. Rectangle r = new Rectangle(4.5, 7.5);
  87. r.Display();
  88. Type type = typeof(Rectangle);
  89. //遍历 Rectangle 类的属性
  90. foreach (Object attributes in type.GetCustomAttributes(false))
  91. {
  92. DeBugInfo dbi = (DeBugInfo)attributes;
  93. if (null != dbi)
  94. {
  95. Console.WriteLine("Bug no: {0}", dbi.BugNo);
  96. Console.WriteLine("Developer: {0}", dbi.Developer);
  97. Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
  98. Console.WriteLine("Remarks: {0}", dbi.Message);
  99. }
  100. }
  101. //遍历方法属性
  102. foreach (MethodInfo m in type.GetMethods())
  103. {
  104. foreach (Attribute a in m.GetCustomAttributes(true))
  105. {
  106. DeBugInfo dbi = (DeBugInfo)a;
  107. if (null != dbi)
  108. {
  109. Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name);
  110. Console.WriteLine("Developer: {0}", dbi.Developer);
  111. Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
  112. Console.WriteLine("Remarks: {0}", dbi.Message);
  113. }
  114. }
  115. }
  116. Console.ReadLine();
  117. }
  118. }
  119. }

编译执行上述代码,得到如下结果:

  1. Length: 4.5
  2. Width: 7.5
  3. Area: 33.75
  4. Bug No: 49
  5. Developer: Nuha Ali
  6. Last Reviewed: 10/10/2012
  7. Remarks: Unused variable
  8. Bug No: 45
  9. Developer: Zara Ali
  10. Last Reviewed: 12/8/2012
  11. Remarks: Return type mismatch
  12. Bug No: 55, for Method: GetArea
  13. Developer: Zara Ali
  14. Last Reviewed: 19/10/2012
  15. Remarks: Return type mismatch
  16. Bug No: 56, for Method: Display
  17. Developer: Zara Ali
  18. Last Reviewed: 19/10/2012
  19. Remarks: