总是有将枚举值输出成特定字符串的需求。假设物体的位置用一个枚举类表示:
public enum ObjectLocationEnum { Top, Bottom, Left, Right, }
UI或者其他地方获取到该枚举的一个值 ObjectLocationEnum.Top ,却期望在当前程序语言为中文时显示“上方”、为英文时显示"upper",甚至在以后的某一天又希望当前程序语言为中文时显示”上面“而不是以前的“上方”。
很显然,上述代码做不到。在设计枚举类型时将Top硬编码成其它字符比如”上方“、”上面“然后直接 instance.ToString() 同样是不满足需求的。
另建一个 Dictionary<ObjectLocationEnum, string> ,通过key找到对应的字符串(或者找到字符串关键字,再根据当前语言找到对应字符串)虽然可以满足需求,但其不仅不优雅,而且以后增加枚举项时要维护多处。
可以通过自定义特性(Attribute)优雅的达到这个目的。
定义EnumResStrAttribute 类:
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public sealed class EnumResStrAttribute : Attribute { public string Key { get; } //关键字 public string DefaultStr { get; } //默认字符串 public EnumResStrAttribute(string key, string defaultStr = null) : base() { Key = key; DefaultStr = defaultStr ?? key; } }
然后在枚举类中应用该特性:
public enum ObjectLocationEnum { [EnumResStr(key: "top", defaultStr: "顶部")] Top, [EnumResStr("bottom", "底部")] Bottom, [EnumResStr("left", "左方")] Left, [EnumResStr("right", "右方")] Right, }
定义一个帮助类:
public static class EnumResStrHelper { public static string GetResStr(Enum value) { System.Diagnostics.Debug.Assert(value != null); //测试用,断言value不为空 if (value == null) throw new ArgumentNullException("value"); var fieldInfo = value.GetType().GetField(value.ToString()); EnumResStrAttribute resStr = (EnumResStrAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(EnumResStrAttribute)); return string.IsNullOrEmpty(resStr.Key) ? resStr.DefaultStr : GetLanguageStr(resStr.Key, resStr.DefaultStr); } //模拟国际化 private static string GetLanguageStr(string key, string defaultStr) { string localStr; //如果是英文,返回英文 if (System.Threading.Thread.CurrentThread.CurrentUICulture.Name == "en") { switch (key) { case "top": localStr = "ding"; break; case "bottom": localStr = "di"; break; case "left": localStr = "zuo"; break; case "right": localStr = "you"; break; default: localStr = defaultStr; break; } } else { switch (key) { case "top": localStr = "顶部"; break; case "bottom": localStr = "底部"; break; case "left": localStr = "左方"; break; case "right": localStr = "右方"; break; default: localStr = defaultStr; break; } } return localStr; } }
大功告成,现在想要获得枚举对应的特定字符串只需要如此调用: EnumResStrHelper.GetResStr(ObjectLocationEnum.Top) 。
除了自定义特性外,也可了解下.net提供的 System.ComponentModel.DataAnnotations.DisplayAttribute 。