在遍历值的同时访问枚举自定义属性

Posted

技术标签:

【中文标题】在遍历值的同时访问枚举自定义属性【英文标题】:Access Enum custom attributes whilst looping over values 【发布时间】:2013-12-05 17:01:09 【问题描述】:

我为一些枚举值添加了一个自定义属性(给它们一个屏幕友好的字符串值)。我正在尝试构建一个在 MVC 页面上使用的 SelectListItems 列表,但我在访问自定义属性时遇到了麻烦。

我的枚举看起来像这样。

public enum MyEnum

   [StringValue("None")] None = 0,
   [StringValue("First Value")] FirstValue = 1,
   [StringValue("Second Value")] SecondValue = 2

属性如下所示。

public class StringValueAttribute : Attribute 

    public StringValueAttribute(string value)
    
        this.StringValue = value;
    

    public string StringValue  get; protected set;         

我创建了一个辅助类,以便我可以轻松地从 Enum 的实例访问 StringValue 属性。

public static string GetStringValue(this Enum value)

    Type type = value.GetType();
    FieldInfo fieldInfo = type.GetField(value.ToString());
    StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
    return attribs != null && attribs.Length > 0 ? attribs[0].StringValue : null;

我可以这样称呼它。

MyEnum test = MyEnum.FirstValue;
string stringValue = test.GetStringValue();

最后,我坚持的代码。我可以轻松地遍历枚举值,但这些值不是 MyEnum 的实例,因此我无法调用我的辅助函数。当我尝试访问 FieldInfo 时,它总是返回 null。这是我目前所拥有的。

public static List<SelectListItem> GetFlagsSelectList<T>(int? selectedValue)

    List<SelectListItem> items = new List<SelectListItem>();
    foreach (int value in Enum.GetValues(typeof(T)))
    
        items.Add(new SelectListItem
        
            Text = Enum.GetName(typeof(T), value), 
            Value = value.ToString(), 
            Selected = selectedValue.HasValue && selectedValue.Value == value
        );
    
    return items;

是否可以在 foreach 循环中访问自定义属性?

编辑:

我想我问的不清楚。我想访问 foreach 循环内的自定义属性。调用 Enum.GetName(typeof(T), value) 只会返回我不想要的属性的名称(例如 FirstValue)。

我想做这样的事情:

foreach (int value in Enum.GetValues(typeof(T)))

    string name = Enum.ToObject(typeof (T), value).GetStringValue();

但是 T 可以是任何类型,所以我不能在那里调用我的 GetStringValue() 方法。

我试过这样做:

foreach (int value in Enum.GetValues(typeof(T)))

    FieldInfo fieldInfo = typeof(T).GetField(value.ToString());
    StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
    string name = attribs != null && attribs.Length > 0 ? attribs[0].StringValue : Enum.GetName(typeof(T), value),;

    items.Add(new SelectListItem
    
        Text = name,
        Value = value.ToString(),
        Selected = selectedValue.HasValue && selectedValue.Value == value
    );

但我总是遇到异常,因为 FieldInfo 对象总是返回 null。

【问题讨论】:

【参考方案1】:

试试

static string GetStringValue2(Enum value) 
 ....


public static List<SelectListItem> GetFlagsSelectList<T>(int? selectedValue) where T : struct 
  var items = new List<SelectListItem>();
  foreach (T value in Enum.GetValues(typeof(T))) 
    var stringValue = GetStringValue2((Enum)(object)value);
    items.Add(new SelectListItem 
      Text = Enum.GetName(typeof(T), value),
      Value = Convert.ToInt32(value).ToString(),
      Selected = selectedValue.HasValue && selectedValue.Value == Convert.ToInt32(value)
    );
  
  return items;

【讨论】:

非常感谢,抱歉在我发布更新之前没有看到您的编辑。【参考方案2】:

不久前我写了一封blog post 来讨论这个问题(XmlEnumAttribute,但这里同样适用)。

public static string ConvertToString(Enum e)

  // Get the Type of the enum
  Type t = e.GetType();

  // Get the FieldInfo for the member field with the enums name
  FieldInfo info = t.GetField(e.ToString("G"));

  // Check to see if the XmlEnumAttribute is defined on this field
  if (!info.IsDefined(typeof(XmlEnumAttribute), false))
  
    // If no XmlEnumAttribute then return the string version of the enum.
    return e.ToString("G");
  

  // Get the XmlEnumAttribute
  object[] o = info.GetCustomAttributes(typeof(XmlEnumAttribute), false);
  XmlEnumAttribute att = (XmlEnumAttribute)o[0];
  return att.Name;

希望对您有所帮助。

【讨论】:

以上是关于在遍历值的同时访问枚举自定义属性的主要内容,如果未能解决你的问题,请参考以下文章

任何人都知道快速获取枚举值的自定义属性的方法吗?

0013JDK源码分析之枚举

如何获取枚举的自定义属性值?

给枚举添加自定义属性

如何通过传入枚举值和属性类型来获取枚举的自定义属性?

如何从自定义用户控件 WPF、C# 中的枚举自定义属性中获取值?