特性基礎
什麼是特性
特性是附加到代碼元素(程序集、類型、成員、參數等)上的元數據。編譯後寫入 IL,可在運行時通過反射讀取或由運行時/框架識別並做相應處理。
定義特性
自定義特性需繼承自 System.Attribute,並可通過 AttributeUsage 限制其作用目標和允許多重使用。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyCustomAttribute : Attribute
{
public string Name { get; }
public MyCustomAttribute(string name) => Name = name;
}
CLR 內置通用特性
| 特性 | 作用 | 示例 |
|---|---|---|
[Obsolete] |
標記已廢棄的 API,調用時報編譯警告或錯誤 | [Obsolete("Use NewMethod instead", true)] public void Old() { } |
[Serializable] |
標記可通過二進制/SOAP 序列化 | [Serializable] public class Person { ... } |
[NonSerialized] |
與 [Serializable] 配合使用,標記字段不參與序列化 |
[NonSerialized] private int _tempCache; |
[DebuggerStepThrough] |
調試時跳過該方法或類,不單步進入 | [DebuggerStepThrough] void Helper() { ... } |
[DebuggerDisplay] |
自定義調試器中顯示的信息 | [DebuggerDisplay("{Id} - {Name}")] public class User { ... } |
[CallerMemberName] |
參數裝飾,獲取調用者的方法名 | void Log([CallerMemberName] string caller = null) { ... } |
[CallerFilePath] |
獲取調用者源文件路徑 | 同上 |
[CallerLineNumber] |
獲取調用者行號 | 同上 |
數據綁定與驗證(Data Annotations)
位於 System.ComponentModel.DataAnnotations,常用於 ASP.NET MVC / EF Core / Blazor 等框架:
| 特性 | 作用 | 示例 |
|---|---|---|
[Required] |
屬性不能為空 | [Required] public string Name { get; set; } |
[StringLength] |
限制字符串最大/最小長度 | [StringLength(100, MinimumLength = 5)] |
[Range] |
數值或日期範圍驗證 | [Range(1, 100)] public int Age { get; set; } |
[RegularExpression] |
正則表達式校驗 | [RegularExpression(@"^\d{3}-\d{4}$")] public string Phone; |
[EmailAddress] |
電子郵件格式驗證 | [EmailAddress] public string Email { get; set; } |
[Key] |
標記實體主鍵(EF Core) | [Key] public int Id { get; set; } |
[Timestamp] |
併發檢查(行版本號) | [Timestamp] public byte[] RowVersion { get; set; } |
[Display(Name="...")] |
指定顯示名稱 | [Display(Name="用户名")] public string UserName { get; set; } |
序列化與 Web API
JSON.NET / System.Text.Json
| 特性 | 作用 | 示例 |
|---|---|---|
[JsonIgnore] |
忽略屬性序列化 | [JsonIgnore] public string InternalNote { get; set; } |
[JsonProperty("name")] |
指定 JSON 字段名稱(Newtonsoft) | [JsonProperty("user_name")] public string Name { get; set; } |
[JsonPropertyName("name")] |
指定 JSON 字段名稱(System.Text.Json) | [JsonPropertyName("user_name")] public string Name { get; set; } |
XML 序列化
| 特性 | 作用 |
|---|---|
[XmlElement("Name")] |
指定元素名 |
[XmlAttribute] |
序列化為 XML 屬性 |
[XmlIgnore] |
忽略字段 |
依賴注入與框架集成
ASP.NET Core
| 特性 | 作用 |
|---|---|
[ApiController] |
啓用自動參數綁定、400 響應等 Web API 特性 |
[Route("api/[controller]")] |
定義控制器路由 |
[HttpGet], [HttpPost] 等 |
標記 Action 支持的 HTTP 動詞 |
[FromServices] |
從 DI 容器中解析參數 |
[FromQuery], [FromBody] 等 |
指定參數綁定來源 |
線程與併發
| 特性 | 作用 |
|---|---|
[MethodImpl(MethodImplOptions.Synchronized)] |
將方法鎖定為單線程訪問 |
[ThreadStatic] |
標記字段為線程靜態,每線程獨立實例 |
[AsyncStateMachine] |
編譯器生成,用於標記 async 方法 |
平台兼容與版本
| 特性 | 作用 |
|---|---|
[SupportedOSPlatform] |
指示 API 在指定平台可用(.NET 5+) |
[UnsupportedOSPlatform] |
指示 API 在指定平台不可用 |
[ObsoletedOSPlatform] |
標記 API 在平台上的過時版本 |
[SupportedOSPlatform("windows")]
public void WindowsOnly() { … }
自定義特性
- 定義:繼承
Attribute - 限制作用目標:使用
[AttributeUsage] - 讀取:通過反射獲取
MemberInfo.GetCustomAttributes<T>()
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class AuditAttribute : Attribute
{
public string Operation { get; }
public AuditAttribute(string operation) => Operation = operation;
}
// 在方法上使用
[Audit("Create"), Audit("Validate")]
public void CreateUser() { … }
優缺點
優點
- 聲明式編程:簡化配置,代碼更清晰。
- 框架集成:與
ASP.NET Core、EF Core等無縫協作。 - 可擴展性:支持自定義特性,擴展功能。
- 跨場景支持:適用
Web、數據庫、測試等。
缺點
- 反射性能:自定義特性使用反射可能影響性能。
- 配置複雜:大量特性可能導致代碼難以維護。
- 調試難度:特性行為需通過反射或日誌調試。
- 依賴框架:部分特性(如
[Route])特定於框架。
使用場景
-
Web API:- 使用
[Route]、[HttpGet]等定義RESTful端點。 - 示例:用户管理
API。
- 使用
-
數據庫映射:
- 使用
[Key]、[Required]配置EF Core模型。 - 示例:批次表頭和明細表。
- 使用
-
模型驗證:
- 使用
[Required]、[StringLength]驗證輸入。 - 示例:導入數據驗證。
- 使用
-
安全控制:
- 使用
[Authorize]、[ValidateAntiForgeryToken]保護端點。 - 示例:管理員導入接口。
- 使用
-
日誌和監控:
- 使用自定義特性(如
[LogExecutionTime])記錄性能。 - 示例:監控導入時間。
- 使用自定義特性(如
-
測試:
- 使用
[Test]、[Fact]編寫單元測試。 - 示例:測試導入邏輯。
- 使用