熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> ASP編程 >> 正文

C#特性學習與使用

2013-11-15 12:51:40  來源: ASP編程 

  C#特性以前的時候用過C#中的特性但只是會用什麼原理有什麼用這些問題不清楚今天就騰出時間學習了一下

  C#中的特性使用Attribute描述在使用時就像是java中的批注一樣不過C#使用中括號特性用來描述我們的數據編譯器能夠識別這些特性以附加信息的形式存放在生成的元數據中供clr使用

  下邊看一個簡單的應用view plainprint?

  static void Main(string[] args)

  { DisplayRunningMsg()DisplayDebugMsg()Trace(方法執行到結尾了!!ConsoleRead()

  } [DllImport(Userdll)] public static extern int MessageBox(int hParent string msg string Caption int type)[Conditional(DEBUG)] private  static  void DisplayRunningMsg()

  { ConsoleWriteLine(This is debugConsoleWriteLine(開始運行Main子程序當前時間是+DateTimeNow)}

  [Conditional(DEBUG)] [Obsolete] private  static  void DisplayDebugMsg()

  { ConsoleWriteLine(該方法已經廢棄啦!!!}

  DllImport特新允許我們引入一個外部的dll下邊做一個函數的聲明我們就可以調用了

  Conditional屬性表示在該種條件下就執行下邊的代碼 所以[Conditional(DEBUG)]此種標識的方法就只有在調試的時候才會在執行   [Obsolete]特性標記該方法已經廢棄

  運行上述代碼輸出(在debug模式下)

   

  看的出來程序執行了[Conditional(DEBUG)]標記的方法如果我們debug改為release那麼再次執行

   

  程序並沒有執行上述方法看的出來由於特性[Conditional(DEBUG)]標記是的在release模式下代碼並沒有運行其標記的函數那麼我們就可以利用這個做一個error trace使其只在debug的模式下輸出當前錯誤信息包括行號方法名位置等這裡要用到 stacktrace類

  Ok說到這裡你應該對特性有了以最最基本的了解

  那麼究竟什麼是特性呢?

  其實特性也是一個類比如[Conditional(DEBUG)]就是構造了以Conditional對象(調用構造方法public Conditional(string type)DllImport(Userdll)對應的也有一個類DllImport下邊我們自定義一個特性你就會明白很多

  首先需要定一個一個類 該類需要集成Attribute使其成為一個特性……NET約定特性類都已Attribute結尾然後在該類中定義一下字段和屬性完成構造

  代碼如下view plainprint?

  [AttributeUsage(AttributeTargetsAllAllowMultiple = trueInherited = true)] class TrackerAttributeAttribute {

  private string opUsernameprivate string opNameprivate DateTime dateTimeprivate string note

  public  TrackerAttribute(string  opUsernamestring  opNamestring date)

  { thisopUsername = opUsernamethisopName = opNamethisdateTime = DateTimeParse(date)}

  //位置參數通過構造函數傳遞值public string  OpUsername { get { return opUsername } }

  public  string  OpName { get { return opName } }

  public  DateTime DateTime { get { return dateTime } }

  //命名參數提供set public string  Note { get { return note } set { note = value } }

  public override string ToString()

  { return 操作人 + opUsername + 操作名 + opName + 時間 + dateTime + 備注 + note}

  嗯他和普通的類幾乎沒什麼差別只不過繼承於Attribute然後他本身又有一些特性我們做逐一介紹我們在類TrackerAttribute 定義了幾個字段完成了構造函數TrackerAttribute(string opUsernamestring  opNamestringdate)

  那麼我麼在使用的時候就需要寫[Tracker(opusernameopnamenote=這是備注)]是的使用類型(參數值參數值)的方法完成了該對象的構造即調用了該類的構造函數構造函數裡與字段對應的參數叫做位置參數因為寫的時候必須位置一一與源構造函數相同其他不通過構造函數傳入參數傳遞的叫做命名參數使用字段名=字段值 的形式賦值這樣完成函數構造和一些屬性的賦值一般情況下我們將位置參數提供get訪問而命名參數則提供get和set因為位置參數已經能夠同感哦構造函數訪問賦值了

  這個特性類上邊還有幾個特性AttributeTargets表示當前特性的作用范圍他是一個位標記的枚舉比如allfieldmethod標記過後智能在相應的地方做該特性書寫比如指定枚舉是作用與字段那麼如果該特性寫在類上邊就會報錯

  如上你的特性類就完成了

  這樣你就可以在其他方法上做該特性的標記了

  我們定義了特性最重要的還是要獲得該特性中的值下邊是獲得的方法view plainprint?

  Type type = typeof(Program)object[] objects = typeGetCustomAttributes(false)foreach (var o in objects)

  { TrackerAttribute trackerAttribute = o as TrackerAttributeif (trackerAttribute != null)

  ConsoleWriteLine(trackerAttributeToString())else { ConsoleWriteLine(獲得對象為空}

  typeGetCustomAttributes(false)該方法將會獲得該類上的所有特性標記返回的是一個object的數組你可以遍歷然後轉換為你的指定特性訪問相應字段即可同樣你也可以通過typegetMethods()[] 獲得一個methodinfo對象然後調用該methodinfo對象的GetCustomAttributes方法即可

  介紹了如上的這些我們利用特性實現為枚舉增加一個獲得其描述的功能

  例如定義枚舉MyEnummyenum=MyEnumTypeA 調用myenumToDescription 可以得到字符串 類型A我們可以想到定一個描述特性然後在各個枚舉元素上做該特性的標記然後提供擴展方法訪問該特性取得該特性值

  代碼如下枚舉定義view plainprint?

  public enum MyType { [Description(A類型)] TypeA[Description(B類型)] TypeB[Description(C類型)] TypeC }

  特性類DescriptionAttribute定義如下view plainprint?

  [AttributeUsage(AttributeTargetsFieldAllowMultiple =trueInherited = true)] class DescriptionAttributeAttribute { private string descriptionpublic  string Description { get { return description } }

  public  DescriptionAttribute(String description)

  { thisdescription = description}

  指定該特性只用於字段定義DescriptionAttribute(String description)構造函數

  Ok現在還缺少枚舉的ToDescription方法C#中的枚舉是不支持定義方法的

  我們可以為其做一個擴展方法擴展方法需要一個靜態類參數前要加this 同時也指定了被擴展的對象調用時可使用擴展對像的實例調用也可以使用該靜態類來調用詳細內容可參考

  擴展類如下view plainprint?

  public  static class Extension {

  public  static string ToDescription(this MyType myEnum)

  { Type type = typeof (MyType)FieldInfo info= typeGetField(myEnumToString())DescriptionAttribute descriptionAttribute= infoGetCustomAttributes(typeof (DescriptionAttribute) true)[] as DescriptionAttributeif (descriptionAttribute != null)

  return descriptionAttributeDescriptionelse return typeToString()}

  這樣MyType就多了一個ToDescription的方法返回的值就是對應的特性值

  在main方法中MyTypemyType = MyTypeTypeBConsoleWriteLine(myTypeToDescription())控制台輸出 B類型 達到了我們想要的效果

  這個方法還是很有用的

  從上邊可以看出我們如果要為一些類添加一些附加的信息 這些附加信息在現實意義與該對象並不是具有真正的對象與屬性關系 無法在原來的裡邊添加字段或者加入字段後很難處理這兩種情況之一都可以使用特性隨後在IL中看一下掉用特性時編譯器都做了什麼事


From:http://tw.wingwit.com/Article/program/ASP/201311/21770.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.