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
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