代码之家  ›  专栏  ›  技术社区  ›  Ryan

本地化枚举描述属性

  •  36
  • Ryan  · 技术社区  · 15 年前

    在.NET中本地化枚举描述的最佳方法是什么?

    (见 Adding descriptions to enumeration constants 对于枚举描述示例)

    理想情况下,我想要一些使用ResourceManager和资源文件的东西,以便与应用程序的其他区域的本地化方式相适应。

    8 回复  |  直到 12 年前
        1
  •  25
  •   Ryan    15 年前

    这就是我最后要说的,我没有看到在添加自定义属性类以保存资源键,然后查找资源文件中的值-为什么不直接使用Enums 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(e.g. 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);       
      }
    }
    
        2
  •  23
  •   Justin    13 年前

    我的解决方案,使用本机描述属性:

    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()

        3
  •  8
  •   Valentin V    15 年前

    有一个简单的解决方案: 使用localizedDescription属性传递资源键。

        [Serializable]
        public class LocalizableDescriptionAttribute:DescriptionAttribute
        {
            public LocalizableDescriptionAttribute(string resourceKey)
                :base(Resources.ResourceManager.GetString(resourceKey))
            { }
    
        }
    
        4
  •  3
  •   Svish    15 年前

    我曾经这样做过的一种方法是在返回字符串的枚举的同一命名空间中添加一个扩展方法。在我的例子中,它只是硬编码的,但是从资源文件中获取它们不会有问题。

        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 ...;
            }
        }
    

    也许不是一个非常平滑或花哨的解决方案,但它起作用=)

        5
  •  1
  •   kerem    12 年前

    将@nairik的方法替换为以下内容,以添加对标志枚举的支持。

    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();
    }
    

    并替换属性中的NameResourceType:

    public Type NameResourceType
    {
        get
        {
            return _resourceType;
        }
        set
        {
            _resourceType = value;
    
            _nameProperty = _resourceType.GetProperty(base.Description, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
        }
    }
    
        6
  •  0
  •   Community basarat    7 年前

    请参阅本问题中的表格示例:

    Localisation/I18n of database data in LINQ to SQL

    状态类型表映射到枚举值。这里真正的好处是,您可以在报表和应用程序之间进行本地化,并指定外部ID与不需要内部值等的第三方集成。它将枚举描述与它的值分离。

        7
  •  0
  •   Richard    15 年前

    不能应用多个System.ComponentModel.DescriptionAttribute(因此该选项为Out)。

    因此,添加一个间接级别,描述包含一个资源名称,然后在资源中使用本地化支持。显然,枚举的用户需要调用helper方法来执行此操作。