如何使用自定义订单属性对枚举进行排序?

时间:2015-06-04 21:06:01

标签: c# enums

我有一个这样的枚举:

enum MyEnum{
 [Order(1)]
 ElementA = 1,
 [Order(0)]
 ElementB = 2,
 [Order(2)]
 ElementC = 3
}

我想列出按我编写的自定义顺序属性排序的元素,以便我得到一个已排序的项目列表。

我正在获取描述属性,但仅适用于这样的一个元素:

FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

它可能是相同的但需要处理所有枚举并返回列表或其他已排序的枚举。

4 个答案:

答案 0 :(得分:9)

假设OrderAttribute类如下:

public class OrderAttribute : Attribute
{
    public readonly int Order;

    public OrderAttribute(int order)
    {
        Order = order;
    }
}

获取枚举值的辅助方法:

public static T[] SortEnum<T>()
{
    Type myEnumType = typeof(T);
    var enumValues = Enum.GetValues(myEnumType).Cast<T>().ToArray();
    var enumNames = Enum.GetNames(myEnumType);
    int[] enumPositions = Array.ConvertAll(enumNames, n =>
    {
        OrderAttribute orderAttr = (OrderAttribute)myEnumType.GetField(n)
            .GetCustomAttributes(typeof(OrderAttribute), false)[0];
        return orderAttr.Order;
    });

    Array.Sort(enumPositions, enumValues);

    return enumValues;
}

答案 1 :(得分:5)

如果我清楚地了解您的问题,可以采用以下解决方案:

public static class EnumExtenstions
{
    public static IEnumerable<TEnum> EnumGetOrderedValues<TEnum>(this Type enumType)
    {

        var fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
        var orderedValues = new List<Tuple<int, TEnum>>();
        foreach (var field in fields)
        {
            var orderAtt = field.GetCustomAttributes(typeof(EnumOrderAttribute), false).SingleOrDefault() as EnumOrderAttribute;
            if (orderAtt != null)
            {
                orderedValues.Add(new Tuple<int, TEnum>(orderAtt.Order, (TEnum)field.GetValue(null)));
            }
        }

        return orderedValues.OrderBy(x=>x.Item1).Select(x=>x.Item2).ToList();
    }
}

用法

var result = typeof(enumType).EnumGetOrderedValues<enumType>();

答案 2 :(得分:1)

鉴于

Value

然后你可以:

Value

所以排序就像:

[AttributeUsage(AttributeTargets.Field)]
public class OrderAttribute : Attribute
{
    public readonly int Order;

    public OrderAttribute(int order)
    {
        Order = order;
    }
}

public static class OrderHelper
{
    public static int GetOrder<TEnum>(TEnum value) where TEnum : struct
    {
        int order;

        if (!OrderHelperImpl<TEnum>.Values.TryGetValue(value, out order))
        {
            order = int.MaxValue;
        }

        return order;
    }

    private static class OrderHelperImpl<TEnum>
    {
        public static readonly Dictionary<TEnum, int> Values;

        static OrderHelperImpl()
        {
            var values = new Dictionary<TEnum, int>();

            var fields = typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public);

            int unordered = int.MaxValue - 1;

            for (int i = fields.Length - 1; i >= 0; i--)
            {
                FieldInfo field = fields[i];

                var order = (OrderAttribute)field.GetCustomAttributes(typeof(OrderAttribute), false).FirstOrDefault();

                int order2;

                if (order != null)
                {
                    order2 = order.Order;
                }
                else
                {
                    order2 = unordered;
                    unordered--;
                }

                values[(TEnum)field.GetValue(null)] = order2;
            }

            Values = values;
        }
    }
}

或LINQ:

int o1 = OrderHelper.GetOrder(MyEnum.ElementA);
int o2 = OrderHelper.GetOrder(MyEnum.ElementB);
int o3 = OrderHelper.GetOrder(MyEnum.ElementC);

var myenums = new[] { MyEnum.ElementA, MyEnum.ElementB, MyEnum.ElementC }; Array.Sort(myenums, (p, q) => OrderHelper.GetOrder(p).CompareTo(OrderHelper.GetOrder(q))); &#34;缓存&#34; var myenums = new[] { MyEnum.ElementA, MyEnum.ElementB, MyEnum.ElementC }; var sorted = myenums.OrderBy(x => OrderHelper.GetOrder(x)); 内的排序。通过知道在枚举中值为OrderHelper字段(您可以很容易地看到它here)来提取枚举的值。

没有OrderHelperImpl<TEnum>的值按照public static中的相同顺序排序,方法是使用Order下方enum的最大可能值

答案 3 :(得分:0)

public class OrderAttribute : Attribute
{
    public int priority;

    public OrderAttribute(int priority)
    {
        this.priority = priority;
    }
}

public enum Test
{
    [Order(1)] value1 = 1,
    [Order(2)] value2 = 2,
    [Order(0)] value3 = 3
}

private static void Main(string[] args)
    {
        Dictionary<string, int> priorityTable = new Dictionary<string, int>();

        var values = Enum.GetValues(typeof (Test)).Cast<Test>();
        MemberInfo[] members = typeof (Test).GetMembers();
        foreach (MemberInfo member in members)
        {
            object[] attrs = member.GetCustomAttributes(typeof(OrderAttribute), false);
            foreach (object attr in attrs)
            {
                OrderAttribute orderAttr = attr as OrderAttribute;

                if (orderAttr != null)
                {
                    string propName = member.Name;
                    int priority = orderAttr.priority;

                    priorityTable.Add(propName, priority);
                }
            }
        }

        values = values.OrderBy(n => priorityTable[n.ToString("G")]);

        foreach (var value in values)
        {
            Console.WriteLine(value);
        }

        Console.ReadLine();
    }

这将输出:

值3

值1

值2