2017-10-06 177 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

這是瘋了:) –