C#的特性Attribute

一、什么是特性

  特性是用于在運行時傳遞程序中各種元素(比如類、方法、結構、枚舉、組件等)的行為信息的聲明性標簽,這個標簽可以有多個。您可以通過使用特性向程序添加聲明性信息。一個聲明性標簽是通過放置在它所應用的元素前面的方括號([ ])來描述的。

  特性可以描述我們的代碼,或者影響應用程序的行為。特性可以用來處理多種問題,比如序列化、數據驗證、程序的安全特征等等。

  特性不是修飾符而是一個有獨特實例化形式的類,繼承于Attributes基類。其實我們在很多地方都能接觸到特性,特性在平時的運用中是非常常見的,比如以下三個場景:

  1.特性[Serializable]標記可序列化的類

  [Serializable]public class MyObject { }

  2.特性[ServiceContract]指名WCF中可以用來對外調用的接口

  [ServiceContract]public interface IService{}

  3.特性[Range]用于MVC中類的屬性的范圍

  [Range(18, 60)]public int Age { get; set; }//年齡范圍

?二、預定義特性

?  .Net框架已經給我們提供了一些預定義的特性,像是上面的三個場景的三個特性我們就可以直接拿來用。這里我們主要介紹另外三個比較基礎的特性,它們都繼承Attribute類,分別是:Obsolete、Conditional和AttributeUsage。

  1.Obsolete

  這個預定義特性標記了不應被使用的程序實體。它可以讓您通知編譯器丟棄某個特定的目標元素。例如,當一個新方法被用在一個類中,但是您仍然想要保持類中的舊方法,您可以通過顯示一個應該使用新方法,而不是舊方法的消息,來把它標記為 obsolete(過時的)。

  • 參數 message,是一個字符串,描述項目為什么過時的原因以及該替代使用什么。
  • 參數 iserror,是一個布爾值。如果該值為 true,編譯器應把該項目的使用當作一個錯誤。默認值是 false(編譯器生成一個警告)。

  示例如下:

    [Obsolete("該方法已經過時,用NewMethod代替", true)]public static void OldMethod(){Console.WriteLine("OldMethod");}

?  2.Conditional

  Conditional標記了一個條件方法,當滿足謀個條件的時候該方法才能執行,多用于程序的調試和診斷。

  示例如下:

    #define Error //宏定義,決定那個方法執行using System;using System.Collections.Generic;using System.Diagnostics;using System.Text;namespace Attribute.Demo{class Program{static void Main(string[] args){Debug();Error();Console.ReadKey();}[Conditional("Debug")]public static void Debug(){Console.WriteLine("Debug");}[Conditional("Error")]public static void Error(){Console.WriteLine("Error");}}}    

  最后結果是:

    Error

?  3.AttributeUsage

  預定義特性 AttributeUsage 描述了如何使用一個自定義特性類。它規定了自定義特性可應用到的項目的類型。這說明了該特性可以描述別的特性,對描述的特性進行某些規定。

  • 參數 validon 規定特性可被放置的語言元素。它是枚舉器 AttributeTargets 的值的組合。默認值是 AttributeTargets.All。
  • 參數 allowmultiple(可選的)為該特性的 AllowMultiple 屬性(property)提供一個布爾值。如果為 true,則該特性是多用的。默認值是 false(單用的)。
  • 參數 inherited(可選的)為該特性的 Inherited 屬性(property)提供一個布爾值。如果為 true,則該特性可被派生類繼承。默認值是 false(不被繼承)。

?  示例如下:

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]

  可以規定多個可放置的語言元素,用標識符 | 分隔開來就行,上述代碼就表示描述的特性可以用于屬性和字段,如果標注在別的如類上就會報錯。

三、自定義特性

  前面有提到預定義的特性都有繼承自定義特性的基類Attribute,那么我們自己實現一個自定義特性也就需要繼承Attribute類。那突然想到既然特性是一個類,那么為什么直接在描述目標前用方括號聲明特性就可以又和一般的類有什么區別呢?主要有以下的一些區別和注意點:

  • 特性的實例化不是通過new的,而是在方括號中調用構造函數。并且構造函數可以有多個,構造函數里的參數為定位參數,定位參數必須放在括號的最前面,按照傳入的定位參數可以調用相應的構造函數來實例化,如果有自己定義的構造函數則必須傳入定位參數進行實例化否則報錯。
  • 特性中屬性的賦值,可以通過具名參數賦值,但是具名參數必須在定位參數后面,順序可以打亂的,具體的形式如ErrorMessage = "年齡不在規定范圍內"。

  接下來我就來自己實現驗證屬性值是否在規定區間內的特性,類似于[Range]。我們定義一個特性MyRangeAttribute繼承基類Attribute,用預定義特性AttributeUsage規定只能用于描述屬性,并自定義構造函數傳入最小值和最大值,并定義方法Validate()校驗,具體如下:

?

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]class MyRangeAttribute : System.Attribute{public MyRangeAttribute(int _min, int _max){this.max = _max;this.min = _min;}private int max;public int Max{get; set;}private int min;public int Min{get; set;}private string errorMessage;public string ErrorMessage{get; set;}public bool Validate(int _value){return _value >= min && _value <= max;}}

?

  接下來,我們創建一個Student類里面有Age屬性并用我們的自定義特性MyRangeAttribute描述,Student類繼承People類,在People類中有方法IsValidate()通過反射執行特性的校驗方法Validate(),具體如下:

    class Student: BaseClass{private int age;[MyRange(0,10, ErrorMessage = "年齡不在規定范圍內")]public int Age{get;set;}}class BaseClass{public bool IsValidate(out string msg){msg = string.Empty;Type type = this.GetType();foreach (var prop in type.GetProperties()){foreach (var attribute in prop.GetCustomAttributes()){object[] parameters = new object[] { (int)prop.GetValue(this, null) };if ((bool)attribute.GetType().GetMethod("Validate").Invoke(attribute, parameters))return true;else{msg = attribute.GetType().GetProperty("ErrorMessage").GetValue(attribute,null).ToString();return false;}}}return false;}}

  我們在控制臺程序中執行如下代碼:

    static void Main(string[] args){string msg = string.Empty;Student student = new Student();while (true){Console.WriteLine("請輸入年齡(輸入exit退出):");string str = Console.ReadLine();if (str.Equals("exit"))break;else{student.Age = Convert.ToInt32(str);if (student.IsValidate(out msg))Console.WriteLine("驗證通過");elseConsole.WriteLine(msg);}}}

  運行可以看到結果如下:

四、結尾

  通過上述的例子可以看出特性可以和反射配合來進行相應的操作,不過反射會消耗性能,并且特性類可以用別的特性描述。

  如果有什么問題可以留言討論!謝謝閱讀。

?

轉載于:https://www.cnblogs.com/xwc1996/p/10145421.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/388804.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388804.shtml
英文地址,請注明出處:http://en.pswp.cn/news/388804.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 技能鑒定_JAVA試題-技能鑒定

一、單選題1.以下創建了幾個對象( B)String A,B,CA"a";B"b":AAB;StringBuffer Dnew StringBuffer("abc");DD.append("567");A.6B.4C.3D.52.關于以下程序段&#xff0c;正確的說法是( C )1&#xff0e;String s1“a”“b”;2&#xff0…

ADD_SHORTCUT_ACTION

String ADD_SHORTCUT_ACTION 動作&#xff1a;在系統中添加一個快捷方式。. “android.intent.action.ADD_SHORTCUT”   String ALL_APPS_ACTION 動作&#xff1a;列舉所有可用的應用。   輸入&#xff1a;無。 “android.intent.action.ALL_APPS”   String ALTERNATIVE…

python3中樸素貝葉斯_貝葉斯統計:Python中從零開始的都會都市

python3中樸素貝葉斯你在這里 (You are here) If you’re reading this, odds are: (1) you’re interested in bayesian statistics but (2) you have no idea how Markov Chain Monte Carlo (MCMC) sampling methods work, and (3) you realize that all but the simplest, t…

java映射的概念_Java 反射 概念理解

文章來源:http://hollischuang.gitee.io/tobetopjavaer/#/basics/java-basic/reflection反射反射機制指的是程序在運行時能夠獲取自身的信息。在java中&#xff0c;只要給定類的名字&#xff0c;那么就可以通過反射機制來獲得類的所有屬性和方法。反射有什么作用在運行時判斷任…

【轉載】移動端布局概念總結

布局準備工作及布局思想及概念: 一個顯示器&#xff08;pc端顯示器 及 手機屏顯示器&#xff09;&#xff0c;既有物理像素&#xff0c;又有獨立像素&#xff08;獨立像素也叫作css像素&#xff0c;用于前端人員使用&#xff09;&#xff1b; -->重要 首先確定設計稿的尺寸…

深入淺出:HTTP/2

上篇文章深入淺出&#xff1a;5G和HTTP里給自己挖了一根深坑&#xff0c;說是要寫一篇關于HTTP/2的文章&#xff0c;今天來還賬了。 本文分為以下幾個部分&#xff1a; HTTP/2的背景HTTP/2的特點HTTP/2的協議分析HTTP/2的支持 HTTP/2簡介 HTTP/2主要是為了解決現HTTP 1.1性能不…

畫了個Android

畫了個Android 今晚瞎折騰&#xff0c;閑著沒事畫了個機器人——android&#xff0c;浪費了一個晚上的時間。畫這丫還真不容易&#xff0c;為那些坐標&#xff0c;差點砸了鍵盤&#xff0c;好在最后畫出個有模有樣的&#xff0c;心稍安。 下面來看看畫這么個機器人需要些什么東…

數據治理 主數據 元數據_我們對數據治理的誤解

數據治理 主數據 元數據Data governance is top of mind for many of my customers, particularly in light of GDPR, CCPA, COVID-19, and any number of other acronyms that speak to the increasing importance of data management when it comes to protecting user data.…

mysql 選擇前4個_mysql從4個表中選擇

不要認為GROUP BY是必需的 . 雖然如果一個孩子有2個父記錄&#xff0c;你可能想用它來將2個父母分組到一行 - 但不確定這是否是你的要求 . 因為如果一個孩子有2個父母&#xff0c;那么將為該孩子返回的父母是未定義的 .假設所有孩子都有父母&#xff0c;所有父母都會有姓&#…

提高機器學習質量的想法_如何提高機器學習的數據質量?

提高機器學習質量的想法The ultimate goal of every data scientist or Machine Learning evangelist is to create a better model with higher predictive accuracy. However, in the pursuit of fine-tuning hyperparameters or improving modeling algorithms, data might …

mysql 集群實踐_MySQL Cluster集群探索與實踐

MySQL集群是一種在無共享架構(SNA&#xff0c;Share Nothing Architecture)系統里應用內存數據庫集群的技術。這種無共享的架構可以使得系統使用低廉的硬件獲取高的可擴展性。MySQL集群是一種分布式設計&#xff0c;目標是要達到沒有任何單點故障點。因此&#xff0c;任何組成部…

Python基礎:搭建開發環境(1)

1.Python語言簡介 2.Python環境 Python環境產品存在多個。 2.1 CPython CPython是Python官方提供的。一般情況下提到的Python就是指CPython&#xff0c;CPython是基于C語言編寫的。 CPython實現的解釋器將源代碼編譯為字節碼&#xff08;ByteCode&#xff09;&#xff0c;再由虛…

python數據結構之隊列(一)

隊列概念隊列&#xff08;queue&#xff09;是只允許在一端進行插入操作&#xff0c;而在另一端進行刪除操作的線性表。隊列是一種先進先出的&#xff08;First In First Out&#xff09;的線性表&#xff0c;簡稱FIFO。允許插入的一端為隊尾&#xff0c;允許刪除的一端為隊頭。…

Android實現圖片放大縮小

Android實現圖片放大縮小 package com.min.Test_Gallery; import Android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Matrix; import android.os.Bun…

matlab散點圖折線圖_什么是散點圖以及何時使用

matlab散點圖折線圖When you were learning algebra back in high school, you might not have realized that one day you would need to create a scatter plot to demonstrate real-world results.當您在高中學習代數時&#xff0c;您可能沒有意識到有一天需要創建一個散點圖…

java判斷題_【Java判斷題】請大神們進來看下、這些判斷題你都知道多少~

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓、判斷改錯題(每題2分&#xff0c;共20分)(正確的打√&#xff0c;錯誤的打并說明原因)1、 Java系統包提供了很多預定義類,我們可以直接引用它們而不必從頭開始編寫程序。 ( )2、 程序可以用字符‘*’替代一個TextField中的每個字…

PoPo數據可視化第8期

PoPo數據可視化 聚焦于Web數據可視化與可視化交互領域&#xff0c;發現可視化領域有意思的內容。不想錯過可視化領域的精彩內容, 就快快關注我們吧 :) 微信訂閱號&#xff1a;popodv_com谷歌決定關閉云可視化服務 Fusion Tables谷歌宣布即將關閉其 Fusion Tables 云服務&#x…

AC自動機題單

AC自動機題目 真的超級感謝xzy 真的幫到我很多 題單 [X] [luogu3808]【模板】AC自動機&#xff08;簡單版&#xff09; https://www.luogu.org/problemnew/show/P3808[X] [luogu3796]【模板】AC自動機&#xff08;加強版&#xff09;https://www.luogu.org/problemnew/show/P37…

java list用法_Java List 用法詳解及實例分析

Java List 用法詳解及實例分析Java中可變數組的原理就是不斷的創建新的數組&#xff0c;將原數組加到新的數組中,下文對Java List用法做了詳解。List:元素是有序的(怎么存的就怎么取出來&#xff0c;順序不會亂)&#xff0c;元素可以重復(角標1上有個3&#xff0c;角標2上也可以…

python字符串和List:索引值以 0 為開始值,-1 為從末尾的開始位置;值和位置的區別哦...

String&#xff08;字符串&#xff09;Python中的字符串用單引號 或雙引號 " 括起來&#xff0c;同時使用反斜杠 \ 轉義特殊字符。 字符串的截取的語法格式如下&#xff1a; 變量[頭下標:尾下標]索引值以 0 為開始值&#xff0c;-1 為從末尾的開始位置。[一個是值&#x…