1. 程式人生 > 其它 >C#中的特性與反射

C#中的特性與反射

一、特性

特性是一個類,用來標記在某個元素上增加一定行為資訊的宣告性標籤。一個宣告性標籤是通過放置在它所應用的元素前面的方括號[]來描述的。

預定義特性

Conditional:這個預定義特性標記了一個條件方法,用於在條件編譯,如[Conditiaol("Debug")]

Obsolete:這個預定義特性標記了不應再使用的程式實體。如果iserror為true時,編譯器將會生成一個錯誤,必須呼叫新的方法來替代

AttributeUsage這個預定義特性描述如何使用一個自定義特性類,如果有自定義特性類時,需要配合它實現相應的功能。

如何自定義特性

1、定義一個類,直接或間接繼承於Attribute

2、約定俗成的以Attribute為字尾,但是這個是可選的

3、以Attribute結尾(為字尾的)的,使用的時候可以省略Attribute

4、標記-修飾:類及類內部的所有元素

5、預設不能重複標記,如果需要重複標記,需要設定AllowMultiple=true,預設是不被繼承的,如果需要則設定inherited=true

特性的功能是通過反射來實現的

using System;
using System.Reflection;
namespace BugFixApplication
{
   // 一個自定義特性 BugFix 被賦給類及其成員
   [AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Constructor 
| AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] public class DeBugInfo : System.Attribute { private int bugNo; private string developer; private string lastReview; public string message; public DeBugInfo(int
bg, string dev, string d) { this.bugNo = bg; this.developer = dev; this.lastReview = d; } public int BugNo { get { return bugNo; } } public string Developer { get { return developer; } } public string LastReview { get { return lastReview; } } public string Message { get { return message; } set { message = value; } } } [DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")] [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")] class Rectangle { // 成員變數 protected double length; protected double width; public Rectangle(double l, double w) { length = l; width = w; } [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")] public double GetArea() { return length * width; } [DeBugInfo(56, "Zara Ali", "19/10/2012")] public void Display() { Console.WriteLine("Length: {0}", length); Console.WriteLine("Width: {0}", width); Console.WriteLine("Area: {0}", GetArea()); } }//end class Rectangle class ExecuteRectangle { static void Main(string[] args) { Rectangle r = new Rectangle(4.5, 7.5); r.Display(); Type type = typeof(Rectangle); // 遍歷 Rectangle 類的特性 foreach (Object attributes in type.GetCustomAttributes(false)) { DeBugInfo dbi = (DeBugInfo)attributes; if (null != dbi) { Console.WriteLine("Bug no: {0}", dbi.BugNo); Console.WriteLine("Developer: {0}", dbi.Developer); Console.WriteLine("Last Reviewed: {0}", dbi.LastReview); Console.WriteLine("Remarks: {0}", dbi.Message); } } // 遍歷方法特性 foreach (MethodInfo m in type.GetMethods()) { foreach (Attribute a in m.GetCustomAttributes(true)) { DeBugInfo dbi = (DeBugInfo)a; if (null != dbi) { Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name); Console.WriteLine("Developer: {0}", dbi.Developer); Console.WriteLine("Last Reviewed: {0}", dbi.LastReview); Console.WriteLine("Remarks: {0}", dbi.Message); } } } Console.ReadLine(); } } }

注意:上面在呼叫DeBugInfo dbi = (DeBugInfo)a;時會報錯

System.InvalidCastException:“Unable to cast object of type 'System.Runtime.CompilerServices.NullableContextAttribute' to type 'testAttribute.DebugInfo'.”

需要修改為    foreach(MethodInfo info in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))

因為預設呼叫的類中含有GetType(),GetHashCode(),ToString()及Equals()等方法