程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#基礎--Attribute(標簽) 和 reflect(反射) 應用

C#基礎--Attribute(標簽) 和 reflect(反射) 應用

編輯:C#入門知識

C#基礎--Attribute(標簽) 和 reflect(反射) 應用


1.Attribute的定義與作用:            公共語言運行時允許你添加類似關鍵字的描述聲明,叫做attributes, 它對程序中的元素進行標注,如類型、字段、方法和屬性等。Attributes和Microsoft .NET Framework文件的元數據保存在一起,可以用來向運行時描述你的代碼,或者在程序運行的時候影響應用程序的行為.比如在WCF中常用的序列化。比如添加的[DataMenber]就是一種標簽。以及xml序列化也是一樣的。      2.Reflect的定義與作用            反射可以用於觀察並修改程序在運行時的執行。一個reflection-oriented程序組件可以監測一個范圍內的代碼執行情況,可以根據期望的目標與此相關的范圍修改本身。這通常是通過在運行時動態分配程序代碼實現。在面向對象的編程語言如Java中,反射允許在編譯期間不知道接口的名稱,字段、方法的情況下在運行時檢查類、接口、字段和方法。它還允許的實例化新對象和調用的方法。(摘抄至維基百科). 其實可以簡單理解為,通過反射可以很輕易的獲取到一個類中的所有方法屬性字段狀態。        3.為了更方便的認識反射以及Attribute的應用,下面有個例子.           業務背景如下: 有個Person對象,目前只有Name和Num屬性,然後要用方法校驗Person對象的合法性。           判斷規則:  1.Name必填,若Name為空,則提示"Name不能為空";                          2.Num可以為空,但是若有數據的話必須由數字組成,若為非數字字符串則彈出"格式不正確".             3.Address可以為空,若有數據的話長度不能超過12,若超過12則提示"Address 長度不能超過12"          需要考慮: 對於Person類,以後熟悉的判斷規則可能會變化,也可能增加屬性,減少屬性。        4.解決方案一:         對於常規解決方案,可能大家會想到。目前只有Name,Address,Num三個屬性,每次我就寫三個代碼段分別對Name,Address,Num驗證。如果增加屬性, 比如增加了公共屬性EmailAddress,那麼就必須添加驗證字符串是否是郵箱的代碼,若刪除了某個屬性,就吧判斷該屬性是否合格的代碼刪除掉不進行判斷。這個也是我最開始想到的方法。不過這樣不好的地方是可維護性不好。改動太大了。而且會導致重復代碼。不如如果需求改成Address不能為空了。那麼在判斷address是否合法的時候還要去添加判斷不能為空的情況。       5.解決方案二:         為了解決方案一的問題,其實我們可以通過Attribute和反射來實現。思路如下:        5.1 首先我們創建一個PersonCheckAttribute對象,他繼承與System.Attribute.    復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;   namespace ReflectTest.Model {     public class PersonCheckAttribute:Attribute     {           // 三個bool變量用於確定是有要驗證這些信息         private bool checkEmpty = false; //是否為空         private bool checkMaxLength = false; //最大長度         private bool checkRegex = false; //用正則表達式驗證參數(是郵箱,是否刷數字)           private int maxLength = 0;         private string regexStr = string.Empty;             public bool CheckEmpty         {             get { return this.checkEmpty; }             set { this.checkEmpty = value; }         }           public bool CheckMaxLength         {             get { return this.checkMaxLength; }             set { this.checkMaxLength = value; }         }           public bool CheckRegex         {             get { return this.checkRegex; }             set { this.checkRegex = value; }         }           public int MaxLength         {             get { return this.maxLength; }             set { this.maxLength = value; }         }           public string RegexStr         {             get { return this.regexStr; }             set { this.regexStr = value; }         }     } } 復制代碼      5.2 然後我們來添加Person類。注意裡面的標簽。       Tips:我在裡面打了標簽,對於5.1的PersonCheckAttribute類中bool變量用來確定是否要進行驗證,公共屬性用來存取判斷參數。      復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;   namespace ReflectTest.Model {     public class Person     {         [PersonCheck(CheckEmpty=true)]         public string Name { get; set; }           [PersonCheck(CheckRegex = true, RegexStr = "^[0-9]*[1-9][0-9]*$")]         public string Num { get; set; }           [PersonCheck(CheckMaxLength = true, MaxLength = 12)]         public string Address { get; set; }     } } 復制代碼    5.3 屬性已經搞定,下面來看看,如何通過反射來獲取類的公共屬性,以及每個屬性的Attribute。       復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ReflectTest.Model; using System.Reflection; using System.Text.RegularExpressions;   namespace ReflectTest.Business {     public class PersonCheck     {         // 獲取所有的錯誤提示         public static string GetErrorMessage(Person person)         {             PropertyInfo[] propertyInfos = person.GetType().GetProperties(); // 獲取一個類的所有屬性             string errorMsg = string.Empty;               //對所有公用屬性(Name,Num,Address)遍歷             foreach (PropertyInfo info in propertyInfos)             {                 errorMsg += GetSignalPropertity(info, person);             }             return errorMsg;         }           // 獲取單個公共屬性的Attribute.也就是model類裡面的[PersonCheck]信息         private static string GetSignalPropertity(PropertyInfo propertyInfo,Person person)         {             // 因為對於此示例,每個Properties(屬性)只有一個Attribute(標簽),所以用了first()來獲取,             // 不過有一點,就是必須在屬性裡面添加[PersonCheck]標簽,但是可以不設置表情裡面的字段.因為沒有的.GetCustomAttributes()返回為null.指向first會報錯.             PersonCheckAttribute attribute = propertyInfo.GetCustomAttributes().First() as PersonCheckAttribute;              string errorMsg = string.Empty;               //以下的if語句是判斷標簽裡面的設置,設置了什麼就執行什麼數據校驗             if (attribute.CheckEmpty)             {                  string obj = propertyInfo.GetValue(person) as string;                  if (string.IsNullOrEmpty(obj))                  {                      errorMsg += Environment.NewLine + string.Format("{0} 不能為空", propertyInfo.Name);                  }             }               if (attribute.CheckMaxLength)             {                 string obj = propertyInfo.GetValue(person) as string;                 if (obj != null && obj.Length > attribute.MaxLength)                 {                     errorMsg += Environment.NewLine + string.Format("{0} 最大長度為{1}", propertyInfo.Name, attribute.MaxLength);                 }             }               // 對於判斷數字郵箱都可以通過正則表達式             if (attribute.CheckRegex)             {                 string obj = propertyInfo.GetValue(person) as string;                 Regex regex = new Regex(attribute.RegexStr);                 if (obj != null && !regex.IsMatch(obj))                 {                     errorMsg += Environment.NewLine + string.Format("{0} 格式不對", propertyInfo.Name);                 }             }               return errorMsg;         }     } }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved