search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

[C#] 透過 Attribute 來為 Enum 表現更多資訊 | 不只是個工程師

對於一個易讀易修改的 code,善用 Enum 來取代單純數值的使用是一種較佳的做法!
然而 Enum 只能對應到數值的應用,若希望有更多的應用 e.g. string、struct、class,etc. 則必須透過為 Enum 附加屬性 (Attribute) 並使用反射 (Reflection) 來取得資訊的方式豐富以 Enum 為出發的系統!

一般的 Enum 通常會是類似這樣的形式:

1
2
3
4
5
6
7
public enum SampleEnum
{
None = 0,
MyEnum01,
MyEnum02,
MyEnum03,
};

然而這樣的 code 只能達到令 None = 0;MyEnum01 = 1;MyEnum02 = 2;MyEnum03 = 3,這樣的狀態而已,如果我希望 None;MyEnum01 … 可以代表一個對應的字串狀態,那就可以透過為 Enum 加上 Attribute 來表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
public enum SampleEnum
{
[System.ComponentModel.DescriptionAttribute("空的")]
None,

[System.ComponentModel.DescriptionAttribute("第一個")]
MyEnum01,

[System.ComponentModel.DescriptionAttribute("第二個")]
MyEnum02,

MyEnum03,
};

要為 Enum 加上 Attribute,只需要在要附加屬性的 Enum 上方用中括號來表示要為某個 Enum 添加一個屬性,並且在中括號內輸入一個 Attribute 的 class,如上述的 code 就是用了一個 system 的 description attribute。因此現在 None、MyEnum01、MyEnum02 都被附加上屬性了,而 MyEnum03 則是沒有被附加上屬性。

當然,若 system 的 description attribute 無法滿足你的需求時,也可以繼承 Attribute Abstract Class 來創造自己的 Attribute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SampleEnumAttribute : Attribute
{
private string _text = string.Empty;

public SampleEnumAttribute(string text)
{
_text = text;
}

public string Text => _text;
}

/* 就可以將上面的 "System.ComponentModel.DescriptionAttribute" 取代成 "SampleEnumAttribute" */
public enum SampleEnum
{
[SampleEnumAttribute("空的")]
None,

[SampleEnumAttribute("第一個")]
MyEnum01,

[SampleEnumAttribute("第二個")]
MyEnum02,

MyEnum03,
};

接著就可以透過 Reflection 來獲得 Attribute 中的資訊:
※ 以下為自定義擴充方法的寫法,若尚不清楚此種用法可以參考:[C#] 如何添加自己的擴充功能讓功能更完善

1
2
3
4
5
6
7
8
9
10
11
12
13
public static class SampleEnumExtension
{
public static string GetSampleEnumText(this SampleEnum sample)
{
System.Reflection.FieldInfo fi = sample.GetType().GetField(sample.ToString());
if (fi.GetCustomAttribute(typeof(SampleEnumAttribute), false) is SampleEnumAttribute attribute)
{
return attribute.Text;
}
else
return null;
}
}

將上述提到的附加屬性 (Attribute) 的方法搭配反射 (Reflection) 結合起來使用,就可以得到如下的結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static void Main(string[] args)
{
var text = string.Empty;
Console.WriteLine("/// ");
text = SampleEnum.None.GetSampleEnumText();
Console.WriteLine($"/// {nameof(SampleEnum.None)} 的 Attribute 訊息: {text}, {nameof(string.IsNullOrEmpty)}: {string.IsNullOrEmpty(text)}");
text = SampleEnum.MyEnum01.GetSampleEnumText();
Console.WriteLine($"/// {nameof(SampleEnum.MyEnum01)} 的 Attribute 訊息: {text}, {nameof(string.IsNullOrEmpty)}: {string.IsNullOrEmpty(text)}");
text = SampleEnum.MyEnum02.GetSampleEnumText();
Console.WriteLine($"/// {nameof(SampleEnum.MyEnum02)} 的 Attribute 訊息: {text}, {nameof(string.IsNullOrEmpty)}: {string.IsNullOrEmpty(text)}");
text = SampleEnum.MyEnum03.GetSampleEnumText();
Console.WriteLine($"/// {nameof(SampleEnum.MyEnum03)} 的 Attribute 訊息: {text}, {nameof(string.IsNullOrEmpty)}: {string.IsNullOrEmpty(text)}");
Console.WriteLine("/// ");
Console.ReadLine();
}

///
/// None 的 Attribute 訊息: 空的, IsNullOrEmpty: False
/// MyEnum01 的 Attribute 訊息: 第一個, IsNullOrEmpty: False
/// MyEnum02 的 Attribute 訊息: 第二個, IsNullOrEmpty: False
/// MyEnum03 的 Attribute 訊息: , IsNullOrEmpty: True
///

可以得到 None、MyEnum01、MyEnum02 的字串訊息、並且 MyEnum03 因為沒有附加 Attribute 所以返回的 string 為 null。

完整的 sample code 我放在 github 上了,歡迎下載玩玩看!

github sample code:https://github.com/leoli-git/MySampleCode/tree/main/MyEnum



熱門推薦

本文由 leotalk-engineerlifecom 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦