枚举的多语言显示(2)——使用Attribute

还是jhh0111昨天关于枚举的双语显示问题的帖子的问题,有不少人跟贴询问使用Attribute的实现,于是刚才乘午间休息实现了一个,这里share一下。
主要框架还是和枚举的多语言显示里一样,对Enum包装了一个DataSource,唯一不同的是里面的每一个Item的DisplayValue采用从Attribute读出,所以这里就不再贴出EnumDataSource代码了(请参考枚举的多语言显示),这里仅仅列出和上篇不同的地方:
 1public 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)。
显然这里的静态方法是很重要的,通过它就可以访问枚举的额外信息了:
  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)]
  5public 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}
使用示例如下:
 1private 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
 8public 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}
你可以从这里下载本篇中的相关示例代码:
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)
posted @ 2008-03-26 14:37  winkingzhang  阅读(3351)  评论(5编辑  收藏  举报