枚举的多语言显示(2)——使用Attribute
还是jhh0111昨天关于枚举的双语显示问题的帖子的问题,有不少人跟贴询问使用Attribute的实现,于是刚才乘午间休息实现了一个,这里share一下。
主要框架还是和枚举的多语言显示里一样,对Enum包装了一个DataSource,唯一不同的是里面的每一个Item的DisplayValue采用从Attribute读出,所以这里就不再贴出EnumDataSource代码了(请参考枚举的多语言显示),这里仅仅列出和上篇不同的地方:
显然这里的静态方法是很重要的,通过它就可以访问枚举的额外信息了:
https://files.cnblogs.com/winkingzhang/Demo_2008_03_26.rar
主要框架还是和枚举的多语言显示里一样,对Enum包装了一个DataSource,唯一不同的是里面的每一个Item的DisplayValue采用从Attribute读出,所以这里就不再贴出EnumDataSource代码了(请参考枚举的多语言显示),这里仅仅列出和上篇不同的地方:
1
public string DisplayValue
2
{
3
get
4
{
5
Dictionary<CultureInfo, EnumItemDescriptionAttribute> disc =
6
EnumItemDescriptionAttribute.GetDisplayValues(_value, typeof(EnumType));
7
CultureInfo currentUICulute = Thread.CurrentThread.CurrentUICulture;
8
if (disc.ContainsKey(currentUICulute))
9
return disc[currentUICulute].Description;
10
return _value.ToString();
11
}
12
}
这里取值是通过EnumItemDescriptionAttribute上的静态Helper方法提供,如果找到对应Culture的Attribute就应用,否则返回默认值(枚举的ToString)。
2

3

4

5

6

7

8

9

10

11

12

显然这里的静态方法是很重要的,通过它就可以访问枚举的额外信息了:
1
/// <summary>
2
/// Define the item of special enum used attribute, you can use it mulitple for multi-descript one enum item.
3
/// </summary>
4
[AttributeUsage(AttributeTargets.Field, AllowMultiple=true)]
5
public class EnumItemDescriptionAttribute : Attribute
6
{
7
/// <summary>
8
/// A cache store, because accessing Attribute is according to reflection, it cost too much
9
/// So I add a cache, which based on special enum Type.
10
/// </summary>
11
private static readonly Dictionary<Type, Dictionary<object, Dictionary<CultureInfo, EnumItemDescriptionAttribute>>> _cache =
12
new Dictionary<Type,Dictionary<object, Dictionary<CultureInfo, EnumItemDescriptionAttribute>>>();
13
/// <summary>
14
/// the culture of Description
15
/// </summary>
16
private CultureInfo _culture;
17
/// <summary>
18
/// the description content.
19
/// </summary>
20
private string _description;
21
22
/// <summary>
23
/// Constructor a new <see cref="EnumItemDescriptionAttribute"/> with special culture name and description.
24
/// </summary>
25
/// <param name="cultureName">the name of special culture, like en-US, zh-CN etc.</param>
26
/// <param name="description">the content of Descroption</param>
27
public EnumItemDescriptionAttribute(string cultureName, string description)
28
: this(CultureInfo.GetCultureInfo(cultureName), description)
29
{
30
}
31
32
/// <summary>
33
/// Constructor a new <see cref="EnumItemDescriptionAttribute"/> with special culture id and description.
34
/// </summary>
35
/// <param name="cultureId">the ID of special culture, like 1033 etc.</param>
36
/// <param name="description">the content of Descroption</param>
37
public EnumItemDescriptionAttribute(int cultureId, string description)
38
: this(CultureInfo.GetCultureInfo(cultureId), description)
39
{
40
}
41
42
/// <summary>
43
/// Internal constructor.
44
/// </summary>
45
/// <param name="culture">special <see cref="CultureInfo"/></param>
46
/// <param name="description">the content of Descroption</param>
47
private EnumItemDescriptionAttribute(CultureInfo culture, string description)
48
{
49
_culture = culture;
50
_description = description;
51
}
52
53
/// <summary>
54
/// Gets the <see cref="CultureInfo"/> for current decription.
55
/// </summary>
56
public CultureInfo Culture
57
{
58
get { return _culture; }
59
}
60
61
/// <summary>
62
/// Gets the description content.
63
/// </summary>
64
public string Description
65
{
66
get { return _description; }
67
}
68
69
/// <summary>
70
/// Gets all <see cref="EnumItemDescriptionAttribute"/>
71
/// for special enum value: <paramref name="value"/> and special enum type: <paramref name="enumType"/>.
72
/// </summary>
73
/// <param name="value">the value of special enum</param>
74
/// <param name="enumType">the enum type of special enum</param>
75
/// <returns>All attributes attatched on special enum value.</returns>
76
public static Dictionary<CultureInfo, EnumItemDescriptionAttribute> GetDisplayValues(object value, Type enumType)
77
{
78
if (enumType == null || !enumType.IsEnum)
79
{
80
throw new NotSupportedException("enumType is not a Enum");
81
}
82
if (value == null || !Enum.IsDefined(enumType, value))
83
{
84
throw new ArgumentException("value is not defined in " + enumType.FullName);
85
}
86
87
return GetDisplayValuesImp(value, enumType);
88
}
89
90
/// <summary>
91
/// Gets the <see cref="EnumItemDescriptionAttribute"/> for special enum value: <paramref name="value"/>,
92
/// special enum type: <paramref name="enumType"/> and special culture.
93
/// </summary>
94
/// <param name="value">the value of special enum</param>
95
/// <param name="enumType">the enum type of special enum</param>
96
/// <param name="culture">special culture for item description.</param>
97
/// <returns>The attributes attatched on special enum value.</returns>
98
public static string GetDisplayValue(object value, Type enumType, CultureInfo culture)
99
{
100
if (enumType == null || !enumType.IsEnum)
101
{
102
throw new NotSupportedException("enumType is not a Enum");
103
}
104
if (value == null || !Enum.IsDefined(enumType, value))
105
{
106
throw new ArgumentException("value is not defined in " + enumType.FullName);
107
}
108
109
if (culture == null)
110
return value.ToString();
111
112
Dictionary<CultureInfo, EnumItemDescriptionAttribute> disc = GetDisplayValuesImp(value, enumType);
113
if (disc.ContainsKey(culture))
114
return disc[culture].Description;
115
return value.ToString();
116
}
117
118
/// <summary>
119
/// Gets all <see cref="EnumItemDescriptionAttribute"/>
120
/// for special enum value: <paramref name="value"/> and special enum type: <paramref name="enumType"/>.
121
/// </summary>
122
/// <param name="value">the value of special enum</param>
123
/// <param name="enumType">the enum type of special enum</param>
124
/// <returns>All attributes attatched on special enum value.</returns>
125
private static Dictionary<CultureInfo, EnumItemDescriptionAttribute> GetDisplayValuesImp(object value, Type enumType)
126
{
127
if (!_cache.ContainsKey(enumType))
128
{
129
Dictionary<object, Dictionary<CultureInfo, EnumItemDescriptionAttribute>> displayValues =
130
new Dictionary<object, Dictionary<CultureInfo, EnumItemDescriptionAttribute>>();
131
foreach (Enum item in Enum.GetValues(enumType))
132
{
133
Dictionary<CultureInfo, EnumItemDescriptionAttribute> descriptions =
134
new Dictionary<CultureInfo, EnumItemDescriptionAttribute>();
135
FieldInfo enumField = enumType.GetField(item.ToString());
136
if (enumField != null)
137
{
138
foreach (EnumItemDescriptionAttribute desc
139
in enumField.GetCustomAttributes(typeof(EnumItemDescriptionAttribute), true))
140
{
141
descriptions.Add(desc.Culture, desc);
142
}
143
}
144
displayValues.Add(item, descriptions);
145
}
146
_cache.Add(enumType, displayValues);
147
}
148
149
return _cache[enumType][value];
150
}
151
}
使用示例如下:
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

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

1
private void Form1_Load(object sender, EventArgs e)
2
{
3
this.comboBox1.DataSource = new EnumDataSource2<Sex>();
4
this.comboBox1.DisplayMember = "DisplayValue";
5
this.comboBox1.ValueMember = "Value";
6
}
7
8
public enum Sex
9
{
10
[EnumItemDescription("zh-CN", "男")]
11
[EnumItemDescription("ja", "男性")]
12
[EnumItemDescription("de", "Männliche")]
13
Male,
14
[EnumItemDescription("zh-CN", "女")]
15
[EnumItemDescription("ja", "女性")]
16
[EnumItemDescription("de", "Weibliche")]
17
Female
18
}
你可以从这里下载本篇中的相关示例代码:
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

https://files.cnblogs.com/winkingzhang/Demo_2008_03_26.rar
To be the apostrophe which changed “Impossible” into “I’m possible”
----------------------------------------------------
WinkingZhang's Blog (http://winkingzhang.cnblogs.com)
GCDN(http://gcdn.grapecity.com/cs)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述