首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 自訂屬性完整指南:從定義、套用到反射讀取

     編輯:關於C#

為什麼需要自訂屬性?

.NET 框架大量使用屬性實現宣告式程式設計,例如 [WebMethod] 將方法暴露為 Web Service、[Conditional("DEBUG")] 控制方法編譯。自訂屬性能將中繼資料嵌入組件,達成鬆耦合設計:程式碼與處理邏輯分離,執行時或設計時透過反射讀取屬性值,動態決定行為。

屬性 vs. 類別屬性:本質差異

比較項目自訂屬性類別屬性
套用目標組件、類別、方法、參數、欄位、介面等所有程式碼元素僅限類別成員
值的來源編譯時硬編碼於原始碼,編入中繼資料,唯讀執行時動態賦值,可讀寫
實例關係套用於類型定義,所有實例共享相同屬性值屬於具體實例,每個實例值獨立

例如:[DefectTrack("1377", "12/15/02", "David")] 套用於類別,該類別所有實例共享此追蹤資訊;若用類別屬性則需每個實例個別設定。

建立自訂屬性類別

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class DefectTrackAttribute : Attribute
{
    private string _defectID, _developerID, _origin, _fixComment;
    private DateTime _modificationDate;

    // 定位參數(必要)
    public DefectTrackAttribute(string defectID, string modDate, string devID)
    {
        _defectID = defectID;
        _modificationDate = DateTime.Parse(modDate);
        _developerID = devID;
    }

    // 命名參數(選擇性,可讀寫)
    public string Origin { get => _origin; set => _origin = value; }
    public string FixComment { get => _fixComment; set => _fixComment = value; }

    // 唯讀屬性對應定位參數
    public string DefectID => _defectID;
    public string ModificationDate => _modificationDate.ToShortDateString();
    public string DeveloperID => _developerID;
}

關鍵點:

  • 繼承 System.Attribute
  • [AttributeUsage] 限定套用目標(AttributeTargets)、是否允許重複(AllowMultiple)、是否繼承(Inherited)
  • 建構函式參數 = 定位參數(必要、唯讀);公開屬性 = 命名參數(選擇性、可讀寫)

套用自訂屬性

[DefectTrack("1377", "12/15/02", "David Tansey")]
[DefectTrack("1363", "12/12/02", "Toni Feltman", Origin = "Coding: Unhandled Exception")]
public class SomeCustomPricingClass
{
    [DefectTrack("1351", "12/10/02", "David Tansey",
        Origin = "Specification: Missing Requirement",
        FixComment = "Added PriceIsValid() function")]
    public bool PriceIsValid(double price) => price > 0 && price < 1000;
}

優勢:屬性值編譯進組件,即使無原始碼也能透過反射讀取,優於傳統註解。

透過反射讀取屬性值

public static void DisplayDefectTrack(string assemblyName)
{
    Assembly asm = Assembly.Load(assemblyName);
    foreach (Type type in asm.GetTypes())
    {
        object[] attrs = type.GetCustomAttributes(typeof(DefectTrackAttribute), false);
        foreach (DefectTrackAttribute attr in attrs)
        {
            Console.WriteLine($"Defect ID: {attr.DefectID}, Date: {attr.ModificationDate}");
        }

        // 同樣處理方法層級屬性
        foreach (MethodInfo mi in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
        {
            object[] mAttrs = mi.GetCustomAttributes(typeof(DefectTrackAttribute), false);
            // ... 輸出屬性值
        }
    }
}

關鍵 API:GetCustomAttributes(Type, bool),第二個參數控制是否搜尋繼承鏈。

設計時與執行時的雙重價值

屬性不僅用於執行時,Visual Studio 設計工具也大量使用(如 [Category]、[Description] 控制屬性視窗顯示)。自訂屬性同樣能擴充設計時體驗,例如打造專屬程式碼產生器、驗證規則引擎等。

總結

自訂屬性是 .NET 中繼資料系統的延伸,讓開發者能將領域知識直接編碼於程式結構中,配合反射實現高度彈性的架構。掌握 AttributeUsage、定位/命名參數、反射讀取三大核心,即可在專案中靈活應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved