枚举的多语言显示
关于枚举类型的多语言显示,其实就是Globalization的问题。解决方案当然不止一种,这里介绍一种可用性和扩展性的比较好的通用方法。
显然这里自己去实现自定义格式化,即通过IFormatable、IFormatProvider、ICustomFormatter等接口已达到Globalization有点小题大作了,而另外一个很容易想到的点是通过DiaplayMember实现显示值得自定义(对于简单Binding,例如ComboBox、ListBox等只用重载ToString就可以了)。
首先,我们希望Binding整个枚举类型的每一个值,也就是说,我们需要把这个枚举的所有值变成一个数据源,为了实现这一点,我们可以使用Enum上的helper方法Enum.GetValues(Type)来返回一个对所有值得枚举,然后依次添加到IList对象或者IListSource接口即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 | if (! typeof (EnumType).IsEnum) { throw new NotSupportedException( "Can not support type: " + typeof (EnumType).FullName); // It's better use resource version as below. // throw new NotSupportedException(SR.GetString("TYPE_NOT_SUPPORT", typeof(EnumType).FullName)); } // Use Enum helper enumerator list all enum values and add to current context. foreach (EnumType value in Enum.GetValues( typeof (EnumType))) { //TODO: add each value to IList base .Add( new EnumAdapter(value)); } |
然后,取到了值,由于我们希望自定义Binding显示,那么需要对枚举值进行封装,而在这个封装里面,我们可以实现多语言的支持。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /// <summary> /// Enum value adapter, used to get values from each Cultures. /// </summary> public sealed class EnumAdapter { /**/ /// <summary> /// Storage the actual Enum value. /// </summary> private EnumType _value; /**/ /// <summary> /// Constructor an <see cref="EnumAdapter"/>. /// </summary> /// <param name="value">The enum value.</param> /// <exception cref=""> /// /// </exception> public EnumAdapter(EnumType value) { if (!Enum.IsDefined( typeof (EnumType), value)) { throw new ArgumentException( string .Format( "{0} is not defined in {1}" , value, typeof (EnumType).Name), "value" ); // It's better use resource version as below. // throw new ArgumentException(SR.GetString("ENUM_NOT_DEFINED_FMT_KEY", value, typeof(EnumType).Name), "value"); } _value = value; } /**/ /// <summary> /// Gets the actual enum value. /// </summary> public EnumType Value { get { return _value; } } /**/ /// <summary> /// Gets the display value for enum value by search local resource with currrent UI lture /// and special key which is concated from Enum type name and Enum value name. /// </summary> /// <remarks> /// This would get correct display value by accessing location resource with current UI Culture. /// </remarks> public string DisplayValue { get { return SR.GetString( string .Format( "{0}.{1}" , typeof (EnumType).Name, _value.ToString())); } } //TODO: If you want more, please add below } |
至此,整个功能的框架已经完成,下面我们来看看一些细节——如何对资源读取和管理的封装:
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 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 | /// <summary> /// Constructor a new <see cref="SR"/>. /// </summary> internal SR() { //TODO: If you modified resource location, please update here this .resources = new System.Resources.ResourceManager( string .Concat( typeof (EnumAdapter).Namespace, ".Resource" ), base .GetType().Assembly); } /**/ /// <summary> /// Get singleton instance. /// </summary> /// <returns>A singleton <see cref="SR"/></returns> private static SR GetLoader() { if (loader == null ) { lock (SR.InternalSyncObject) { if (loader == null ) { loader = new SR(); } } } return loader; } /**/ /// <summary> /// Gets an object from resources by special key, which provided by <paramref name="name"/>. /// </summary> /// <param name="name">Resource accessed key</param> /// <returns>return stored object in resource. if resource not found, return <paramref name="name"/> as object.</returns> public static object GetObject( string name) { SR loader = GetLoader(); if (loader == null ) { return null ; } try { return loader.resources.GetObject(name, Culture); } catch { } return name; } /**/ /// <summary> /// Gets a string from resources by special key, which provided by <paramref name="name"/>. /// </summary> /// <param name="name">Resource accessed key</param> /// <returns>return stored string in resource. If resource not found, retuen <paramref name="name"/> as result.</returns> public static string GetString( string name) { SR loader = GetLoader(); if (loader == null ) { return null ; } try { return loader.resources.GetString(name, Culture); } catch { } return name; } /**/ /// <summary> /// Gets a formatted string from resources by special key, which provided by <paramref name="name"/> and optional parameters. /// </summary> /// <param name="name">Resource accessed key</param> /// <param name="args">format arguments.</param> /// <returns>return stored string in resource. If resource not found, use <paramref name="name"/> as formator, return the formatted string.</retur public static string GetString( string name, params object [] args) { SR loader = GetLoader(); if (loader == null ) { return null ; } string format = name; try { format = loader.resources.GetString(name, Culture); } catch { } if ((args == null ) || (args.Length <= 0)) { return format; } // It's better cut long arg for formating. for ( int i = 0; i < args.Length; i++) { string arg = args[i] as string ; if ((arg != null ) && (arg.Length > 0x400)) { args[i] = arg.Substring(0, 0x3fd) + "" ; } } return string .Format(System.Globalization.CultureInfo.CurrentCulture, format, args); } |
OK,大功告成,有了这么一个封装,在应用里就可以简单的这么几句够搞定。
1 2 3 4 5 6 7 8 9 10 11 12 | private void Form1_Load( object sender, EventArgs e) { this .comboBox1.DataSource = new EnumDataSource<Sex>(); this .comboBox1.DisplayMember = "DisplayValue" ; this .comboBox1.ValueMember = "Value" ; } public enum Sex { Male, Female } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?