【问题标题】:Linking enum value with localized string resource将枚举值与本地化字符串资源链接
【发布时间】:2012-07-17 22:28:32
【问题描述】:

相关: Get enum from enum attribute

我想要一种最易于维护的方式来绑定枚举,并将其与本地化字符串值相关联。

如果我将枚举和类放在同一个文件中,我会觉得有点安全,但我必须假设有更好的方法。我也考虑过让枚举名称与资源字符串名称相同,但恐怕我不能总是在这里强制执行。

using CR = AcmeCorp.Properties.Resources;

public enum SourceFilterOption
{
    LastNumberOccurences,
    LastNumberWeeks,
    DateRange
    // if you add to this you must update FilterOptions.GetString
}

public class FilterOptions
{
    public Dictionary<SourceFilterOption, String> GetEnumWithResourceString()
    {
        var dict = new Dictionary<SourceFilterOption, String>();
        foreach (SourceFilterOption filter in Enum.GetValues(typeof(SourceFilterOption)))
        {
            dict.Add(filter, GetString(filter));
        }
        return dict;
    }

    public String GetString(SourceFilterOption option)
    {
        switch (option)
        {
            case SourceFilterOption.LastNumberOccurences:
                return CR.LAST_NUMBER_OF_OCCURANCES;
            case SourceFilterOption.LastNumberWeeks:
                return CR.LAST_NUMBER_OF_WEEKS;
            case SourceFilterOption.DateRange:
            default:
                return CR.DATE_RANGE;
        }
    }
}

【问题讨论】:

  • 你绑定字典了吗?

标签: c# .net enums encapsulation


【解决方案1】:

您可以为每个枚举值添加 DescriptionAttribute。

public enum SourceFilterOption
{
    [Description("LAST_NUMBER_OF_OCCURANCES")]
    LastNumberOccurences,
    ...
}

当你需要的时候拉出描述(资源键)。

FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute),     
if (attributes.Length > 0)
{
    return attributes[0].Description;
}
else
{
    return value.ToString();
}

http://geekswithblogs.net/paulwhitblog/archive/2008/03/31/use-the-descriptionattribute-with-an-enum-to-display-status-messages.aspx

编辑:对 cme​​ts (@Tergiver) 的回应。在我的示例中使用(现有的)DescriptionAttribute 是为了快速完成工作。您最好实现自己的自定义属性,而不是使用其目的之外的属性。像这样的:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inheritable = false)]
public class EnumResourceKeyAttribute : Attribute
{
 public string ResourceKey { get; set; }
}

【讨论】:

  • 我喜欢这个,虽然我可能会创建一个像 ResourceNameAttribute 这样的新属性。我会让它打开一段时间,看看是否有更好的结果,但我已经在更新我的代码了。谢谢。
  • 呃,投反对票,想解释一下吗?它不工作吗?因为它比我的解决方案更好。
  • +1 虽然我也不希望为此滥用现有属性
  • 呃,这不适用于我的特定用例(本地化字符串)。当我这样做时: public enum SourceFilterOption { [LocalizedString(CR.LAST_NUMBER_OF_OCCURANCES)] LastNumberOccurences } 我得到“属性参数必须是常量”。
  • @Joe,在属性中使用 CONSTANT 资源键。属性参数必须是常量。在运行时从属性中获取值时,使用该值作为资源文件的键。
【解决方案2】:

如果有人没有正确更新它,你可能会立即崩溃。

public String GetString(SourceFilterOption option)
{
    switch (option)
    {
        case SourceFilterOption.LastNumberOccurences:
            return CR.LAST_NUMBER_OF_OCCURANCES;
        case SourceFilterOption.LastNumberWeeks:
            return CR.LAST_NUMBER_OF_WEEKS;
        case SourceFilterOption.DateRange:
            return CR.DATE_RANGE;
        default:
            throw new Exception("SourceFilterOption " + option + " was not found");
    }
}

【讨论】:

  • +1 表示默认情况下的异常。我讨厌在 switch/case 语句中看到枚举返回(有效)值的默认情况。这真的可以隐藏错误...
【解决方案3】:

我通过以下方式映射到资源: 1. 定义一个类 StringDescription,ctor 获取 2 个参数(资源类型及其名称)

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
class StringDescriptionAttribute : Attribute
{
    private string _name;
    public StringDescriptionAttribute(string name)
    {
        _name = name;
    }

    public StringDescriptionAttribute(Type resourseType, string name)
    {
            _name = new ResourceManager(resourseType).GetString(name);

    }
    public string Name { get { return _name; } }
}
  1. 为任一文化创建资源文件(例如 WebTexts.resx 和 Webtexts.ru.resx)。让我们成为红色,绿色等颜色......

  2. 定义枚举:

    枚举颜色{ [StringDescription(typeof(WebTexts),"Red")] 红色=1 , [StringDescription(typeof(WebTexts), "Green")] 绿色 = 2, [StringDescription(typeof(WebTexts), "Blue")] 蓝色 = 3, [StringDescription("疯狂黑眼圈")] AntracitWithMadDarkCircles

    }

  3. 定义一个通过反射获取资源描述的静态方法

    公共静态字符串 GetStringDescription(Enum en) {

        var enumValueName = Enum.GetName(en.GetType(),en);
    
        FieldInfo fi = en.GetType().GetField(enumValueName);
    
        var attr = (StringDescriptionAttribute)fi.GetCustomAttribute(typeof(StringDescriptionAttribute));
    
        return attr != null ? attr.Name : "";
    }
    
  4. 吃:

    颜色颜色; col = 颜色.红色; Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");

        var ListOfColors = typeof(Colour).GetEnumValues().Cast<Colour>().Select(p => new { Id = p, Decr = GetStringDescription(p) }).ToList();
    
        foreach (var listentry in ListOfColors)
            Debug.WriteLine(listentry.Id + " " + listentry.Decr);
    

【讨论】:

    【解决方案4】:

    根据文化从资源文件中获取枚举描述值的最简单方法

    我的枚举

      public enum DiagnosisType
        {
            [Description("Nothing")]
            NOTHING = 0,
            [Description("Advice")]
            ADVICE = 1,
            [Description("Prescription")]
            PRESCRIPTION = 2,
            [Description("Referral")]
            REFERRAL = 3
    

    }

    我已将资源文件和密钥与枚举描述值相同

    Resoucefile and Enum Key and Value Image, Click to view resouce file image

       public static string GetEnumDisplayNameValue(Enum enumvalue)
        {
            var name = enumvalue.ToString();
            var culture = Thread.CurrentThread.CurrentUICulture;
            var converted = YourProjectNamespace.Resources.Resource.ResourceManager.GetString(name, culture);
            return converted;
        }
    

    在视图上调用此方法

      <label class="custom-control-label" for="othercare">YourNameSpace.Yourextenstionclassname.GetEnumDisplayNameValue(EnumHelperClass.DiagnosisType.NOTHING )</label>
    

    它将按照您的文化返回字符串accordig

    【讨论】:

      【解决方案5】:

      我必须在 WPF 中使用它,这是我的实现方式

      首先你需要定义一个属性

      public class LocalizedDescriptionAttribute : DescriptionAttribute
      {
          private readonly string _resourceKey;
          private readonly ResourceManager _resource;
          public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
          {
              _resource = new ResourceManager(resourceType);
              _resourceKey = resourceKey;
          }
      
          public override string Description
          {
              get
              {
                  string displayName = _resource.GetString(_resourceKey);
      
                  return string.IsNullOrEmpty(displayName)
                      ? string.Format("[[{0}]]", _resourceKey)
                      : displayName;
              }
          }
      }
      

      您可以像这样使用该属性

      public enum OrderType
      {
          [LocalizedDescription("DineIn", typeof(Properties.Resources))]
          DineIn = 1,
          [LocalizedDescription("Takeaway", typeof(Properties.Resources))]
          Takeaway = 2
      }
      

      然后定义一个像这样的转换器

      public class EnumToDescriptionConverter : IValueConverter
      {
          public object Convert(object value, Type targetType, object parameter, CultureInfo language)
          {
              var enumValue = value as Enum;
      
              return enumValue == null ? DependencyProperty.UnsetValue : enumValue.GetDescriptionFromEnumValue();
          }
      
          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo language)
          {
              return value;
          }
      }
      

      然后在你的 XAML 中

      <cr:EnumToDescriptionConverter x:Key="EnumToDescriptionConverter" />
      
      <TextBlock Text="{Binding Converter={StaticResource EnumToDescriptionConverter}}"/>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多