本地化枚举描述属性
在.net中本地化枚举描述的最佳方法是什么?
(有关枚举描述示例,请参阅为枚举常量添加描述 )
理想情况下,我希望使用ResourceManager和资源文件,以适应其他应用程序本地化。
这是我结束了,我没有看到添加自定义属性类来保存资源键,然后查找资源文件的价值 – 为什么不使用枚举typename +值作为资源键?
using System; using System.Resources; using System.Reflection; public class MyClass { enum SomeEnum {Small,Large}; private ResourceManager _resources = new ResourceManager("MyClass.myResources", System.Reflection.Assembly.GetExecutingAssembly()); public string EnumDescription(Enum enumerator) { string rk = String.Format("{0}.{1}",enumerator.GetType(),enumerator); string localizedDescription = _resources.GetString(rk); if (localizedDescription == null) { // A localized string was not found so you can either just return // the enums value - most likely readable and a good fallback. return enumerator.ToString(); // Or you can return the full resourceKey which will be helpful when // editing the resource files(eg MyClass+SomeEnum.Small) // return resourceKey; } else return localizedDescription; } void SomeRoutine() { // Looks in resource file for a string matching the key // "MyClass+SomeEnum.Large" string s1 = EnumDescription(SomeEnum.Large); } }
我的解决scheme,使用本机parsing属性:
public class LocalizedEnumAttribute : DescriptionAttribute { private PropertyInfo _nameProperty; private Type _resourceType; public LocalizedEnumAttribute(string displayNameKey) : base(displayNameKey) { } public Type NameResourceType { get { return _resourceType; } set { _resourceType = value; _nameProperty = _resourceType.GetProperty(this.Description, BindingFlags.Static | BindingFlags.Public); } } public override string Description { get { //check if nameProperty is null and return original display name value if (_nameProperty == null) { return base.Description; } return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null); } } } public static class EnumExtender { public static string GetLocalizedDescription(this Enum @enum) { if (@enum == null) return null; string description = @enum.ToString(); FieldInfo fieldInfo = @enum.GetType().GetField(description); DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes.Any()) return attributes[0].Description; return description; } }
枚举声明
public enum MyEnum { [LocalizedEnum("ResourceName", NameResourceType = typeof(ResourceType))] Test = 0 }
然后调用MyEnumInstance.GetLocalizedDescription()
有一个简单的解决scheme:使用LocalizedDescription属性来传递资源密钥。
[Serializable] public class LocalizableDescriptionAttribute:DescriptionAttribute { public LocalizableDescriptionAttribute(string resourceKey) :base(Resources.ResourceManager.GetString(resourceKey)) { } }
我曾经做过的一种方法是在相同的命名空间中添加一个扩展方法作为返回string的枚举。 在我的情况下,它只是硬编码,但从资源文件中获取它们没有任何问题。
public static string Describe(this SomeEnum e) { switch(e) { SomeEnum.A: return "Some text from resourcefile"; SomeEnum.B: return "Some other text from resourcefile"; ...: return ...; } }
也许不是一个极其平滑或奇特的解决scheme,但它的工作原理=)
将下面的@ nairik方法replace为添加对枚举枚举的支持。
public static string GetLocalizedDescription(this Enum @enum) { if ( @enum == null ) return null; StringBuilder sbRet = new StringBuilder(); string description = @enum.ToString(); var fields = description.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach ( var field in fields ) { FieldInfo fieldInfo = @enum.GetType().GetField(field); DescriptionAttribute[] attributes = ( DescriptionAttribute[] )fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); if ( attributes.Any() ) sbRet.AppendFormat("{0}, ", attributes[0].Description); else sbRet.AppendFormat("{0}, ", field); } if ( sbRet.Length > 2 ) sbRet.Remove(sbRet.Length - 2, 2); return sbRet.ToString(); }
并replace属性中的NameResourceType:
public Type NameResourceType { get { return _resourceType; } set { _resourceType = value; _nameProperty = _resourceType.GetProperty(base.Description, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } }
在这个问题中查看我的表格示例:
LINQ to SQL中的数据库数据的本地化/ I18n
状态types表映射到枚举值。 这里真正的好处是,你可以在你的报表和整个应用程序中进行本地化,并指定外部ID以便与不需要内部值的第三方进行集成等。它将枚举描述从它的值中分离出来。
您不能有多个System.ComponentModel.DescriptionAttribute应用(以便选项)。
因此,添加一个间接级别,该描述包含一个资源名称,然后在资源中使用本地化支持。 显然,这个枚举的用户需要调用你的帮助器方法来执行此操作。
这看起来不错: http : //www.codeproject.com/Articles/19980/Data-Binding-an-Enum-with-Descriptions