選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
3 分鐘閱讀時間 (666 個字)

[C#] 客製 Attribute

unsplash-coding104

C# 的 Attribute 

用來陳述 code 跟特定訊息的關聯,很像 Java 中的 Annotation。

[ApiController] // Attribute for class
[Route("api/[controller]")] // Attribute for class with parameter
public class BookController : ControllerBase
{
	[HttpGet] // Attribute for method
	public ActionResult Get()
	{
		// ...
	}

	[HttpGet("{bookId}")] // Attribute for method with parameter
	public ActionResult Get(int bookId)
	{
		// ...
	}
} 

 常見的 Attribute 的目標有

  • 類別 (Class)
  • 介面 (Interface)
  • 列舉 (Enum)
  • 屬性 (Property)
  • 方法 (Method)
  • 參數 (Parameter)

 客製一個 Attribute

客製一個最簡單的 Attribute (沒有帶任何參數),
只需要建立一個 Attribute Class 、繼承 Attribute ,便可使用:

public class Not4InsertAttribute : Attribute
{
}

public class Book
{
	[Not4Insert] // Or [Not4InsertAttribute]
	public int Id { get; set; }
} 

 Attribute 的參數

  1. Constructor 參數組成的 Positional parameter: 可用於必填時的驗證
  2. Public 、非 Get-only Property 組成的 Named parameter: 常用於可選的參數
public class Not4InsertAttribute : Attribute
{
	// named parameter
	public int? OnlyWhenLessThan { get; set; }
}

public class GreaterThanAttribute : Attribute
{
	// named parameter
	public bool AllowEqual { get; set; } = false;

	private int GreaterThan { set; }

	public GreaterThanAttribute (int greaterThan)	// positional parameter
	{
		GreaterThan = greaterThan;
	}
}

public class Book
{
	// Attribute without parameter
	[Not4Insert]
	public int Id { get; set; }

	// Attribute with named parameter
	[Not4Insert(OnlyWhenLessThan = 1)]
	// Attribute with positional parameter
	[GreaterThan(0)]
	public int AuthorId { get; set; }

	// Attribute with positional parameter & named parameter
	[GreaterThan(1, AllowEqual = true)]
	public int PublisherId { get; set; }
} 

 Attribute 參數類型限制

Attribute 的參數必須為下列類型:

  • boolbytechardoublefloatintlongsbyteshortstringuintulongushortobjectSystem.Type之一
  • public 的 enum
  • 上述類型的一維陣列。

(在建立 Attribute 時, IDE 可能不會提示建立了不符合類型限制的參數,但會造成編譯錯誤 。)

 限制 Attribute 的使用: AttributeUsageAttribute

[AttributeUsageAttribute(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public class Not4InsertAttribute : Attribute
{} 

 參數

  • (Positional) ValidOn: AttributeTargets 限制可以套用 Attribute 的目標類型,以 | 隔開多個值。
...

AttributeTargets 列舉 (System) | Microsoft Docs

指定有效套用屬性的應用程式項目。Specifies the application elements on which it is valid to apply an attribute.
  • (Named) AllowMultiple: bool設定同一個目標是否能夠多次套用此 Attribute ,預設值為 false。
// AllowMultiple為false時會編譯錯誤
[ExampleAttribute]
[ExampleAttribute(10)]
public class ForExample
{
} 
  • (Named) Inherited: bool設定衍生類別是否繼承套用此 Attribute ,預設值為 true。
[InheritedExampleAttribute]
public class ForExample
{
	[InheritedExampleAttribute]
	public virtual void MakeExample() {}
}

// Inherited 為 true 時,
// Implementation 也會套用 InheritedExampleAttribute
public class Implementation : ForExample
{
	// Inherited 為 true 時,
	// override 的 MakeExample 也會套用 InheritedExampleAttribute
	public override void MakeExample() {}
} 

 取得 Attribute: Attribute.GetCustomAttribute

// 如果沒有找到會回傳 null
Attribute? GetCustomAttribute (Target element, Type attributeType, bool inherit = false) 
  • element: 取得 Attribute 的來源可以是 ParameterInfoMemberInfoAssemblyModule
  • attributeType: typeof(客製的 Attribute)
  • inherit: 是否在祖先(Ancestor)類別搜尋 Attribute (不帶值的話是 false)
public class Not4InsertAttribute : Attribute
{
	public int? OnlyWhenLessThan { get; set; }
}

public class Book
{
	[Not4Insert]
	public int Id { get; set; }
}

public static void Main(string[] args)
{
	// ...
	foreach(var propInfo in typeof(Book).GetProperties())
	{
		// 記得轉型,才拿得到 Property
		var attribute = (Not4InsertAttribute) Attribute
			.GetCustomAttribute(propInfo, typeof(Not4InsertAttribute));
		var onlyWhenLessThan = attribute.OnlyWhenLessThan;
	}

	// ...
} 
OWASP Top 10 2017 - SQL Injection
Jenkins Pipeline Stages 平行處理的寫法

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/07, 週二

Captcha 圖像