2017-10-06 16 views
2

Comment puis-je convertir les méthodes GetWithOrder pour renvoyer l'énumération actuelle dans le bon ordre? Cela fonctionne pour la chaîne de l'enum, mais je veux la valeur Enum réelle, plus elle doit être générique bien sûr.Renvoyer la liste enum au lieu de la chaîne dans l'extension d'extension helper

[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

Je me demande simplement - pourquoi auriez-vous un ordre de membres enum qui n'est pas classé par ordre alphabétique ou par valeur? –

+0

Peut-être parce qu'ils sont stockés dans une base de données, et l'ajout de nouvelles énumérations peut avoir besoin d'être mis dans un certain ordre lorsqu'il est affiché, mais pas lié à la valeur stockée. –

+0

Cela n'aurait-il pas plus de sens de mettre le 'EnumOrderAttribute' sur les valeurs' Enum' et de simplement le vérifier lors de l'itération de 'Enum.GetValues ​​()'? – DiskJunky

Répondre

4

méthode d'extension pour la variable de type ENUM n'a pas de sens parce que vous n'avez pas besoin d'une valeur de cette variable - vous avez besoin uniquement de type ENUM. Donc, j'irais avec classe d'aide statique:

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); 
    } 
} 

Note: type ENUM a un champ value non statique qui détient en fait la valeur de l'ENUM. Vous n'avez donc besoin de prendre que des champs statiques si vous voulez lister les membres d'enum.

Utilisation

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

Pour l'échantillon ENUM

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

sortie sera

[ Lemon, Apple, Banana ] 

Membres sans EnumOrder attribut passer en dernier, mais vous pouvez changer ce comportement si vous voulez utilisez un autre ordre par défaut au lieu de Int32.MaxValue.

+0

C'est fou :) –