enum类型是一种符号标记,便于开发者在程序编码中使用,从而避免数字类的状态标记。正是因为其主要是用于代码层面,所以设计之初就没有考虑过本地化的支持。但是,在很多情况下,我们都需要绑定enum类型到一个类似于ComboBox的控件以提供用户选择项,这个时候,本地化就显得必要了。当然,enum的本地化方式多种多样,本文试图探讨一种利用DataAnnotation的方法间接实现本地化。
首先,定义一个DeviceType类型,并使用DataAnnotation方式标记enum类型的本地化资源(具体请参考DataAnnotation),示例中提供了英文和中文的两个资源文件,默认英文。
public enum DeviceType { [Display(Name="laptop",ResourceType=typeof(ApplicationResource))] LapTop, [Display(Name = "desktop", ResourceType = typeof(ApplicationResource))] Desktop, [Display(Name = "mobile", ResourceType = typeof(ApplicationResource))] MobilePhone, [Display(Name = "router", ResourceType = typeof(ApplicationResource))] Router, [Display(Name = "fax", ResourceType = typeof(ApplicationResource))] Fax }
然后,编写一个扩展方法,用于将enum类型转换为Dictionary<int,string>类型的字典,其中int为enum项的常量值,string为该enum项的本地化字符串,具体如下:
public static class EnumExtension { public static DictionaryToDictionary(this Type enumType) { if (!enumType.IsEnum) { throw new ArgumentException("Type must be enum!"); } Dictionary enumStrings = new Dictionary (); //查看枚举类型中的每项,如果有DisplayAttribute,则使用其本地化的字符串资源,否则,直接使用枚举的默认名称 int[] enumValues = Enum.GetValues(enumType) as int[]; foreach (int v in enumValues) { string enumName = Enum.GetName(enumType, v); DisplayAttribute[] attributes = enumType.GetField(enumName).GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[]; if (attributes == null || attributes.Length < 1) { enumStrings.Add(v, enumName); } else { ResourceManager mgr = new ResourceManager(attributes[0].ResourceType); enumStrings.Add(v,mgr.GetString(attributes[0].Name)); } } return enumStrings; } }
然后,在任何需要枚举类型的控件上直接绑定ToDictionary方法返回的字典即可。如下例中在Silverlight中:
public MainPage() { InitializeComponent(); comboBox.ItemsSource = typeof(DeviceType).ToDictionary(); comboBox.SelectedIndex = 0; comboBox.DisplayMemberPath = "Value"; comboBox.SelectedValuePath = "Key"; }
这样,在设置了线程的语言文化Thread.CurrentCulture后即可实现枚举类型的本地化。