c# 獲取特性的接口的實(shí)現(xiàn)
在 C# 中,并沒有一個專門的“獲取特性的接口”(即沒有類似 IGetAttribute 這樣的接口供你實(shí)現(xiàn)或調(diào)用)。
獲取特性(Attributes)是通過 反射(Reflection) 機(jī)制完成的,主要依賴以下兩個核心類/方法:
System.Attribute類:提供了靜態(tài)方法來獲取特性。System.Reflection命名空間下的類型:如Type,MethodInfo,PropertyInfo等,它們提供了實(shí)例方法GetCustomAttributes。
以下是獲取特性的三種主要方式:
1. 使用Attribute.GetCustomAttribute(推薦用于獲取單個)
這是最傳統(tǒng)且語義清晰的方法,適用于當(dāng)你確定只需要獲取一個特定類型的特性時(shí)。
- 位置:
System命名空間 - 特點(diǎn):如果找到返回該特性實(shí)例,找不到返回
null。如果同一元素上有多個同類特性且AllowMultiple=true,它只返回第一個。
using System;
using System.Reflection;
// 假設(shè) MyClass 上有一個 [MyAttribute]
Type type = typeof(MyClass);
// 獲取單個特性
var attr = (MyAttribute)Attribute.GetCustomAttribute(type, typeof(MyAttribute));
if (attr != null)
{
Console.WriteLine(attr.Description);
}泛型版本 (.NET Core / .NET 5+ 更常用):
// 語法更簡潔,無需強(qiáng)制轉(zhuǎn)換 var attr = Attribute.GetCustomAttribute<MyAttribute>(type);
2. 使用MemberInfo.GetCustomAttributes(推薦用于獲取多個)
這是 Type, MethodInfo, PropertyInfo 等反射對象的實(shí)例方法。適用于需要獲取所有特性,或者不確定是否有多個同名特性的情況。
- 位置:
System.Reflection命名空間 - 特點(diǎn):返回一個數(shù)組 (
object[]或T[])。
using System;
using System.Reflection;
using System.Linq;
Type type = typeof(MyClass);
// 獲取該類型上所有的 MyAttribute 實(shí)例
var attrs = type.GetCustomAttributes<MyAttribute>(inherit: true).ToArray();
foreach (var attr in attrs)
{
Console.WriteLine(attr.Description);
}
// 如果不指定泛型,返回 object[]
var allAttrs = type.GetCustomAttributes(inherit: true); 3. 使用ICustomAttributeProvider接口 (底層機(jī)制)
雖然你通常不直接使用它,但值得了解的是,所有可以應(yīng)用特性的元素(如 Type, Assembly, MethodInfo)都實(shí)現(xiàn)了 System.Reflection.ICustomAttributeProvider 接口。
這個接口定義了兩個核心方法,上述的 GetCustomAttributes 方法本質(zhì)上就是調(diào)用這里:
- object[] GetCustomAttributes(bool inherit)
- object[] GetCustomAttributes(Type attributeType, bool inherit)
示例(通常不需要這樣寫,除非你在做非常底層的反射框架):
// Type 類實(shí)現(xiàn)了 ICustomAttributeProvider ICustomAttributeProvider provider = typeof(MyClass); var attrs = provider.GetCustomAttributes(typeof(MyAttribute), true);
關(guān)鍵參數(shù)說明:inherit
在調(diào)用 GetCustomAttributes 時(shí),通常會看到一個 bool inherit 參數(shù):
true: 不僅檢查當(dāng)前元素,還會沿著繼承鏈向上查找基類或基接口上的特性(前提是特性定義時(shí)[AttributeUsage(Inherited = true)])。false: 只檢查當(dāng)前元素直接聲明的特性。
現(xiàn)代 C# 模式匹配寫法 (C# 7.0+)
在實(shí)際開發(fā)中,結(jié)合 is 模式匹配可以讓代碼更簡潔:
var method = typeof(MyClass).GetMethod("DoWork");
// 檢查并獲取
if (method.GetCustomAttribute<ObsoleteAttribute>() is ObsoleteAttribute obsAttr)
{
Console.WriteLine($"該方法已過時(shí): {obsAttr.Message}");
}
// 或者檢查是否存在任意特性
if (method.GetCustomAttributes<AuthorizationAttribute>().Any())
{
// 執(zhí)行授權(quán)邏輯
}總結(jié)
| 需求 | 推薦方法 | 返回類型 |
|---|---|---|
| 獲取單個特定特性 | Attribute.GetCustomAttribute<T>(member) | T (找不到為 null) |
| 獲取所有特定特性 | member.GetCustomAttributes<T>() | IEnumerable<T> |
| 獲取所有特性(不限類型) | member.GetCustomAttributes() | object[] |
| 底層接口 | ICustomAttributeProvider | object[] |
注意:為了性能考慮,.NET 6 及更高版本引入了 System.Reflection.CustomAttributeExtensions,上述泛型方法大多擴(kuò)展自此類,性能優(yōu)于舊的非泛型方法。
到此這篇關(guān)于c# 獲取特性的接口的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)c# 獲取特性接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#簡易圖片格式轉(zhuǎn)換器實(shí)現(xiàn)方法
這篇文章主要介紹了C#簡易圖片格式轉(zhuǎn)換器實(shí)現(xiàn)方法,涉及C#基于WinForm操作圖片的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
C#實(shí)現(xiàn)在控制臺輸出當(dāng)前系統(tǒng)時(shí)間的方法
這篇文章主要介紹了C#實(shí)現(xiàn)在控制臺輸出當(dāng)前系統(tǒng)時(shí)間的方法,涉及C#時(shí)間函數(shù)DateTime.Now的使用方法,需要的朋友可以參考下2015-04-04
C# 前端無插件打印導(dǎo)出實(shí)現(xiàn)方式詳解
本文講述了使用C#實(shí)現(xiàn)前端無插件的打印和導(dǎo)出功能,介紹了相關(guān)技術(shù)和方法,適合需要在項(xiàng)目中實(shí)現(xiàn)相應(yīng)功能的開發(fā)者參考2024-10-10
CAD2008+VS2008開發(fā)ObjectARX加載失敗問題(推薦)
這篇文章主要介紹了CAD2008+VS2008開發(fā)ObjectARX加載失敗問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
解析如何正確使用SqlConnection的實(shí)現(xiàn)方法
本篇文章對如何正確使用SqlConnection的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

