.NET标志枚举:获取值的属性

3

您好,StackOverflow:

如果我有一个带有标记属性的枚举类型,并且这个枚举类型中的值都有自己的属性,那么我该如何检索所有适当的属性?

例如:

[Flags()]
enum MyEnum
{
    [EnumDisplayName("Enum Value 1")]
    EnumValue1 = 1,
    [EnumDisplayName("Enum Value 2")]
    EnumValue2 = 2,
    [EnumDisplayName("Enum Value 3")]
    EnumValue3 = 4,
}

void Foo()
{
    var enumVar = MyEnum.EnumValue2 | MyEnum.EnumValue3;

    // get a collection of EnumDisplayName attribute objects from enumVar
    ...
}
1个回答

8

使用Linq的快速而简单的方法:

IEnumerable<EnumDisplayNameAttribute> attributes = 
    Enum.GetValues(typeof(MyEnum))
        .Cast<MyEnum>()
        .Where(v => enumVar.HasFlag(v))
        .Select(v => typeof(MyEnum).GetField(v.ToString()))
        .Select(f => f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)[0])
        .Cast<EnumDisplayNameAttribute>();

或者使用查询语法:

IEnumerable<EnumDisplayNameAttribute> attributes = 
    from MyEnum v in Enum.GetValues(typeof(MyEnum))
    where enumVar.HasFlag(v)
    let f = typeof(MyEnum).GetField(v.ToString())
    let a = f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)[0]
    select ((EnumDisplayNameAttribute)a);

或者,如果每个字段可能有多个属性,您可能会想要这样做:

IEnumerable<EnumDisplayNameAttribute> attributes = 
    Enum.GetValues(typeof(MyEnum))
        .Cast<MyEnum>()
        .Where(v => enumVar.HasFlag(v))
        .Select(v => typeof(MyEnum).GetField(v.ToString()))
        .SelectMany(f => f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false))
        .Cast<EnumDisplayNameAttribute>();

或者使用查询语法:

IEnumerable<EnumDisplayNameAttribute> attributes = 
    from MyEnum v in Enum.GetValues(typeof(MyEnum))
    where enumVar.HasFlag(v))
    let f = typeof(MyEnum).GetField(v.ToString())
    from EnumDisplayNameAttribute a in f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
    select a;

我可能需要更多的咖啡,但是 Where(v => (enumVar & v) != v) 子句正确吗?难道不应该是 (enumVar & v) == v 或者 (enumVar & v) != 0 吗?编辑:算了,让我去喝杯咖啡。第二次编辑:不,我想我是对的。天哪,我快疯了。 - Chris Sinclair
@ChrisSinclair 是的,我一开始用的是!= 0,但后来意识到== v可能更好(但没有修复!=),但实际上.HasFlag(v)在我看来比两者都要好。我想我也需要喝咖啡:p - p.s.w.g
1
我使用 FirstOrDefault() 代替索引器 [0] 来处理可能没有此属性的标志。然后,我检查列表中的空值并做出适当的反应。 - martinoss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接