How to sort enum using a custom order attribute?

前端 未结 4 1652
陌清茗
陌清茗 2020-12-30 06:51

I have an enum like this:

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

And I want to li

4条回答
  •  情书的邮戳
    2020-12-30 07:00

    Given

    [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 value) where TEnum : struct
        {
            int order;
    
            if (!OrderHelperImpl.Values.TryGetValue(value, out order))
            {
                order = int.MaxValue;
            }
    
            return order;
        }
    
        private static class OrderHelperImpl
        {
            public static readonly Dictionary Values;
    
            static OrderHelperImpl()
            {
                var values = new Dictionary();
    
                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;
            }
        }
    }
    

    You can then:

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

    So sorting is like:

    var myenums = new[] { MyEnum.ElementA, MyEnum.ElementB, MyEnum.ElementC };
    Array.Sort(myenums, (p, q) => OrderHelper.GetOrder(p).CompareTo(OrderHelper.GetOrder(q)));
    

    or for LINQ:

    var myenums = new[] { MyEnum.ElementA, MyEnum.ElementB, MyEnum.ElementC };
    var sorted = myenums.OrderBy(x => OrderHelper.GetOrder(x));
    

    The OrderHelper "caches" the ordering inside a OrderHelperImpl. The values of the enum are extracted by knowing that in enums the values are public static fields (you can easily see it here).

    Values without an Order are ordered in the same ordering they are present in the enum, by using the greatest possible values of an int just below int.MaxValue

提交回复
热议问题