C# 反射和特性(自定義特性)

自定義特性

你或許已經注意到了,應用特性的語法和之前見過的其他語法有很大不同。你可能會覺得特
性是一種完全不同的結構類型,其實不是,特性只是一種特殊的類。
有關特性類的一些要點如下。

  • 用戶自定義的特性類叫作自定義特性。
  • 所有特性類都派生自System.Attribute。

聲明自定義特性

總體來說,聲明一個特性類和聲明其他類一樣。然而,有一些事項值得注意,如下所示。

  • 要聲明一個自定義特性,需要做如下工作。
    • 聲明一個派生自System.Attribute的類。
    • 給它起一個以后綴Attribute結尾的名字。
  • 安全起見,通常建議你聲明一個sealed的特性類。
    例如,下面的代碼顯示了MyAttributeAttribute特性的聲明的開始部分:

image
由于特性持有目標的信息,所有特性類的公有成員只能是:

  • 字段
  • 屬性
  • 構造函數

使用特性的構造函數

特性和其他類一樣,有構造函數。每一個特性必須至少有一個公共構造函數。

  • 和其他類一樣,如果你不聲明構造函數,編譯器會為你產生一個隱式、公共且無參的構
    造函數。
  • 特性的構造函數和其他構造函數一樣,可以被重載。
  • 聲明構造函數時必須使用類全名,包括后綴。只可以在應用特性時使用短名稱。
    例如,如果有如下的構造函數(名字沒有包含后綴),編譯器會產生一個錯誤消息
public MyAttributeAttribute(string desc,string ver)
{Description = desc;VersionNumber = ver;
}

指定構造函數

當我們為目標應用特性時,其實是在指定應該使用哪個構造函數來創建特性的實例。列在特
性應用中的參數其實就是構造函數的實參。
例如,在下面的代碼中,MyAttribute被應用到一個字段和一個方法上。對于字段,聲明指定
了使用帶單個字符串參數的構造函數。對于方法,聲明指定了使用帶兩個字符串參數的構造函數。

[MyAttribute("Holds a value")]  //使用一個字符串的構造函數
public int MyField;[MyAttribute("Version 1.3", "Galen Daniel")] //使用兩個字符串的構造函數
public void MyMethod()
{...
}

特性構造函數的其他要點如下。

  • 在應用特性時,構造函數的實參必須是在編譯時能確定值的常量表達式。
  • 如果應用的特性構造函數沒有參數,可以省略圓括號。例如,如下代碼中的兩個類都使
    用MyAttr特性的無參構造函數。兩種形式的意義是相同的。
[MyAttr]
class SomeClass...[MyAttr]
class OtherClass...

使用構造函數

和其他類一樣,我們不能顯式調用構造函數。特性的實例被創建后,只有特性的消費者訪問
特性時才能調用構造函數。這一點與其他類的實例不同,這些實例都創建在使用對象創建表達式
的位置。應用一個特性是一條聲明語句,它不會決定什么時候構造特性類的對象。
圖25-4比較了普通類構造函數的使用和特性的構造函數的使用。

  • 命令語句的實際意義是:“在這里創建新的類。
  • 聲明語句的意義是:“這個特性和這個目標相關聯,如果需要構造特性,則使用這個構造
    函數。

構造函數中的位置參數和命名參數

與普通類的方法和構造函數相似,特性的構造函數同樣可以使用位置參數和命名參數。
如下代碼顯示了使用一個位置參數和兩個命名參數來應用一個特性:

[MyAttribute("An execellent class",Reviewer="Amy McArthur",Ver="0.7.15.33)]

下面的代碼演示了特性類的聲明以及為MyClass類應用特性。注意,構造函數的聲明只列出了
一個形參,但我們可通過命名參數給構造函數3個實參。兩個命名參數設置了字段ver和Reviewer
的值。

public sealed class MyAttributeAttribute:System.Attribute
{public string Description;public string Ver;public string Reviewer;public MyAttributeAttribute(string desc) //一個形參{Description=desc;}
}[MyAttribute("An execellent class",Reviewer="Amy McArthur",Ver="7.15.33")]
class MyClass
{...
}

說明 和方法一樣,構造函數需要的任何位置參數都必須放在命名參數之前。

限制特性的使用

我們已經看到了可以為類應用特性。但特性本身就是類,有一個很重要的預定義特性可以應
用到自定義特性上,那就是AttributeUsage特性。我們可以使用它來限制將特性用在某個目標類
例如,如果希望自定義特性MyAttribute只能應用到方法上,那么可以以如下形式使用
AttributeUsage:

[AttributeUsage(AttributeUsage.Method)]
public sealed class MyAttributeAttribute:System.Attribute
{...
}

AttributeUsage有3個重要的公有屬性,如表25-4所示。表中顯示了屬性名和屬性的含義。
對于后兩個屬性,還顯示了它們的默認值。

名 字定 義默 認 值
ValidOn保存能應用特性的目標類型列表。構造函數的第一個參數必須是 AttributeTargets 類型的枚舉值
Inherited一個布爾值,它指示特性是否可被裝飾類型的派生類所繼承true
AllowMultiple一個布爾值,指示目標上是否可應用特性的多個實例false

AttributeUsage的構造函數
AttributeUsage的構造函數接受單個位置參數,該參數指定了可使用特性的目標類型。它用這
個參數來設置Valid0n屬性,可接受的目標類型是AttributeTargets枚舉的成員。AttributeTargets
枚舉的完整成員列表如表25-5所示。

可以通過使用按位或運算符來組合使用類型。例如,在下面的代碼中,被裝飾的特性只能應
用到方法和構造函數上。

[AttributeUsage(AttributeTarget.Method|AttributeTarget.Constructor)]
public sealed class MyAttributeAttribute:System.Attribute
{...
}
AllAssemblyClassConstructor
DelegateEnumEventField
GenericParameterInterfaceMethodModule
ParameterPropertyReturnValueStruct

當為特性聲明應用AttributeUsage時,構造函數至少需要一個必需的參數,參數包含的目標
類型會保存在Valid0n中。還可以通過使用命名參數有選擇地設置lnherited和AllowMu1tiple
屬性。如果不設置,它們會保持如表25-4所示的默認值。
作為示例,下面一段代碼指定了MyAttribute的如下方面。

  • MyAttlibute能且只能應用到類上。
  • MyAttribute不會被應用它的類的派生類所繼承。
  • 不能在同一個目標上應用MyAttribute的多個實例。
[AttributeUsage(AttributeTarget.Class,//必需的位置參數Inherited=false,      //可選的命名參數AllowMultiple=false)] //可選的命名參數public sealed class MyAttributeAttribute:System.Attribute
{...
}

自定義特性的最佳實踐

強烈推薦編寫自定義特性時參考如下實踐。

  • 特性類應該表示目標結構的某種狀態。
  • 如果特性需要某些字段,可以通過包含具有位置參數的構造函數來收集數據,可選字段
    可以采用命名參數按需初始化。
  • 除了屬性之外,不要實現公有方法或其他函數成員。
  • 為了更安全,把特性類聲明為sealed。
  • 在特性聲明中使用AttributeUsage來顯式指定特性目標組。
    如下代碼演示了這些準則:
[AttributeUsage(AttributeTargets.Class)]
public sealed class ReviewCommentAttribute:System.AttributeTargets
{public string Description{get;set;}public string VersionNumber{get;set;}public string ReviewerID{get;set;}public ReviewCommentAttribute(string desc,string ver){Description=desc;VersionNumber=ver;}
}

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

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

相關文章

科目二的四個電路

一.K21電動機單連續運轉接線(帶點動控制)1.電路圖2.主線路這可很明了,是一條直線,從上接到下就OK了,然后從熱繼電器出來,接到SB3按鈕的常閉觸點上接著往下走一端接到SB2的常閉觸點上,接著往下走,走到接觸器的線圈上,從L2借一條火線出來,從熔斷器的上端接入,另一端接…

【位運算】查詢子數組最大異或值|2693

本文涉及知識點 位運算、狀態壓縮、枚舉子集匯總 3277. 查詢子數組最大異或值 給你一個由 n 個整數組成的數組 nums,以及一個大小為 q 的二維整數數組 queries,其中 queries[i] [li, ri]。 對于每一個查詢,你需要找出 nums[li…ri] 中任…

HTML DOM 方法

HTML DOM 方法 引言 HTML DOM(文檔對象模型)是HTML文檔的編程接口,它允許開發者通過JavaScript來操作HTML文檔中的元素。DOM 方法是DOM編程的核心,它提供了豐富的操作手段來改變網頁的結構、樣式和行為。本文將詳細介紹HTML DOM中…

w嵌入式分享合集68

自己的原文哦~ https://blog.51cto.com/whaosoft/14133002 一、一鍵開關機電路的設計方案 方案一:電路圖 一鍵開關機電路分析如下: 電路工作流程如下: Key按下瞬間,Q2、Q1導通,7805輸入電壓在8.9V左右&…

FFmpeg QoS 處理

FFmpeg 中的 QoS (服務質量) 處理主要關注于實時流媒體傳輸中的時序控制、丟幀策略和網絡適應等方面。以下是 FFmpeg 中 QoS 相關的關鍵機制和配置方法。1. 基本 QoS 機制丟幀策略 (Frame Dropping)cAVDictionary *options NULL; av_dict_set(&options, "framedrop&q…

TexStudio中的Latex,PDFLatex,XeLatex和LuaLatex的區別

多種LaTeX編譯器一、多種LaTeX編譯器 1.1 PDFLaTeX(1994年) 默認、最常用的引擎。 輸入文件通常是 ASCII 或 UTF-8 編碼(但中文需要 CJK 宏包或 ctex 宏包支持)。 字體選擇受限:只能使用 TeX 自帶的字體或者 Type 1…

容器化部署:用Docker封裝機器翻譯模型與服務詳解

文章目錄一、機器翻譯容器化的技術棧選型1.1 為什么需要容器化MT模型?1.2 基礎鏡像選擇對比1.3 典型依賴分層方案1.4 性能對比(容器化 vs 原生部署)二、關鍵部署模式2.1 輕量級API服務封裝2.2 模型熱更新策略三、Docker鏡像構建3.1 編寫Docke…

leetcode_42 接雨水

1. 題意 給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。 2. 題解 這個題不會做,全部是看得題解捏。 不過能看懂題解感覺自己也很棒了! 看完題解后感覺最難的是如何求出有多少…

Spring Boot 整合 Thymeleaf 模板引擎:從零開始的完整指南

引言:為什么選擇 Thymeleaf? Thymeleaf 是一個現代化的服務器端 Java 模板引擎,專為 Web 開發而設計。與 JSP 不同,Thymeleaf 模板是純 HTML 文件,可以直接在瀏覽器中預覽,無需后端服務器支持。這種"…

pytest介紹(python測試框架)(@pytest.mark.parametrize、@pytest.fixtures)

文章目錄**1. 核心特點**- **簡潔易用**:無需復雜的配置,只需編寫簡單的函數或類即可進行測試。- **豐富的斷言**:直接使用 Python 內置的 assert 語句,失敗時提供詳細的錯誤信息。- **自動發現測試**:通過約定的命名規…

[Python 基礎課程]繼承

在 Python 的面向對象編程(OOP)中,繼承(Inheritance) 是一種重要的機制,它允許一個類(稱為子類或派生類)從另一個類(稱為父類、基類或超類)中繼承屬性和方法。…

QT之設計器組件功能(8大類55個組件)

組件名稱 功能描述關鍵屬性1. Layouts(布局組件)(1) Vertical Layout(垂直布局)將子控件按垂直方向依次排列layoutSpacing:控件之間的間距layoutMargin:布局邊緣的邊距layoutStretch:設置各控件…

java中list的api詳細使用

在Java中,List是集合框架中最常用的接口之一,繼承自Collection,代表有序、可重復的元素集合(允許null元素)。其核心實現類有ArrayList(數組實現,隨機訪問高效)、LinkedList&#xff…

Azure AI Search 探索總結

Azure AI Search 原名 Azure Cognitive Service,是Azure中用來給AI項目構建知識庫的組件。知識庫本質和數據庫很像,但是內部的存儲結構和檢索算法不一樣。比如并不是知識庫的每一列都可以用來過濾、檢索或group by,而是要根據實際情況配置。A…

高效解決 pip install 報錯 SSLError: EOF occurred in violation of protocol

高效解決 pip install 報錯 SSLError: EOF occurred in violation of protocol 標簽: Python, pip, SSLError, Clash, 網絡代理, 問題解決 一、問題描述 在Python開發中,pip 是我們最親密的伙伴。然而,當你身處需要科學上網的環境&#xff0c…

CSS 核心知識點全解析:從基礎到實戰應用

大家好!今天這篇文章將系統總結 CSS 的核心知識點,從最基礎的樣式引入到復雜的選擇器應用,再到盒子模型、文本處理等實戰技巧,全程結合代碼示例,讓你輕松掌握 CSS 的精髓。一、CSS 是什么?為什么需要它&…

ClickHouse的學習與了解

什么是ClickHouse? ClickHouse是一個用于聯機分析(OLAP)的列式數據庫管理系統(DBMS)。 在傳統的行式數據庫系統中,數據按如下順序存儲:RowWatchIDJavaEnableTitleGoodEventEventTime#0893543506621Investor Relations12016/5/18 5:19#1903295…

安卓11 12系統修改定制化_____修改系統 解鎖system分區 去除data加密 自由刪減系統應用

在定制化系統中。修改系統分區 解鎖system。讓用戶可以自由刪減應用。這個在定制化服務中比較常見。對于此項修改服務。需要我們了解基礎的分區常識以及常用的幾種基礎修改步驟。 通過博文了解?????? 1??????-----修改rom 解鎖 system 分區有什么意義 2????…

JetPack系列教程(八):PDF庫——讓Android應用也能優雅“翻頁”

JetPack系列教程(八):PDF庫——讓Android應用也能優雅“翻頁” 在Android開發的世界里,加載PDF文件一直是個讓人又愛又恨的“小妖精”。愛它,因為PDF是文檔界的“萬能鑰匙”;恨它,因為原生Andr…

Three.js三大組件:場景(Scene)、相機(Camera)、渲染器(Renderer)

上一篇中我們學習了第一個Three.js場景"Hello World"。這一篇就來學習three.js的核心組件。 此圖來源(Three.js中文網) three.js的核心由三大組件構成:場景(Scene)、相機(Camera)和渲染器(Renderer)。下面我將詳細介紹這三大件的作…