2017-10-06 183 views
2

如何将GetWithOrder方法转换为按正确顺序返回实际枚举?它适用于枚举的字符串,但我想要实际的枚举值,当然它需要是通用的。在枚举扩展帮助中返回枚举列表而不是字符串

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] 
public class EnumOrderAttribute : Attribute 
{ 
    public int Order { get; set; } 
} 


public static class EnumExtenstions 
{ 
    public static IEnumerable<string> GetWithOrder(this Enum enumVal) 
    { 
     return enumVal.GetType().GetWithOrder(); 
    } 

    public static IEnumerable<string> GetWithOrder(this Type type) 
    { 
     if (!type.IsEnum) 
     { 
      throw new ArgumentException("Type must be an enum"); 
     } 
     // caching for result could be useful 
     return type.GetFields() 
           .Where(field => field.IsStatic) 
           .Select(field => new 
              { 
               field, 
               attribute = field.GetCustomAttribute<EnumOrderAttribute>() 
              }) 
           .Select(fieldInfo => new 
              { 
               name = fieldInfo.field.Name, 
               order = fieldInfo.attribute != null ? fieldInfo.attribute.Order : 0 
              }) 
           .OrderBy(field => field.order) 
           .Select(field => field.name); 
    } 
} 

public enum TestEnum 
{ 
    [EnumOrder(Order=2)] 
    Second = 1, 

    [EnumOrder(Order=1)] 
    First = 4, 

    [EnumOrder(Order=3)] 
    Third = 0 
} 

var names = typeof(TestEnum).GetWithOrder(); 
var names = TestEnum.First.GetWithOrder(); 
+0

只是想知道 - 为什么你会有没有按字母顺序或按价值排序的枚举成员的顺序? –

+0

也许是因为它们存储在数据库中,并且添加新的枚举可能需要在显示时按特定顺序放置,但与存储的值无关。 –

+0

把'EnumOrderAttribute'放在'Enum'值上并且在迭代Enum.GetValues()'时检查它是否更有意义? – DiskJunky

回答

4

枚举类型变量的扩展方法是没有意义的,因为您不需要该变量的值 - 您只需要枚举类型。所以,我会去与静态辅助类:

public static class Enum<T> 
{ 
    public static IEnumerable<T> GetOrderedValues() 
    { 
     var type = typeof(T); 
     if (!type.IsEnum) 
      throw new InvalidOperationException(); 

     return from f in type.GetFields(BindingFlags.Static | BindingFlags.Public) 
       orderby f.GetCustomAttribute<EnumOrderAttribute>()?.Order ?? Int32.MaxValue 
       select (T)f.GetValue(obj: null); 
    } 
} 

注:枚举类型非静态value场,其实际持有的枚举值。所以如果你想列举枚举成员,你只需要使用静态字段。

使用

var values = Enum<Fruits>.GetOrderedValues(); 

对于样品枚举

public enum Fruits 
{ 
    Banana, 
    [EnumOrder(2)] 
    Apple, 
    [EnumOrder(1)] 
    Lemon 
} 

输出将被

[ Lemon, Apple, Banana ] 

成员没有EnumOrder属性将在最后一次去,但如果你愿意,你可以改变这种行为使用其他一些默认订单而不是Int32.MaxValue

+0

这是疯了:) –