Order by enum description

前端 未结 6 1598
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-13 10:55

I am working on an ASP.NET MVC projet using EF code first, and I am facing a situation where I need to order by an enum description:

public partial class Ite         


        
6条回答
  •  悲哀的现实
    2021-01-13 11:18

    I would go with dynamic expression. It's more flexible and can easily be changed w/o affecting the database tables and queries.

    However, instead of sorting by description strings in the database, I would create ordered map in memory, associating int "order" value with each enum value like this:

    public static class EnumHelper
    {
        public static Expression> DescriptionOrder(this Expression> source)
            where TEnum : struct
        {
            var enumType = typeof(TEnum);
            if (!enumType.IsEnum) throw new InvalidOperationException();
    
            var body = ((TEnum[])Enum.GetValues(enumType))
                .OrderBy(value => value.GetDescription())
                .Select((value, ordinal) => new { value, ordinal })
                .Reverse()
                .Aggregate((Expression)null, (next, item) => next == null ? (Expression)
                    Expression.Constant(item.ordinal) :
                    Expression.Condition(
                        Expression.Equal(source.Body, Expression.Constant(item.value)),
                        Expression.Constant(item.ordinal),
                        next));
    
            return Expression.Lambda>(body, source.Parameters[0]);
        }
    
        public static string GetDescription(this TEnum value)
            where TEnum : struct
        {
            var enumType = typeof(TEnum);
            if (!enumType.IsEnum) throw new InvalidOperationException();
    
            var name = Enum.GetName(enumType, value);
            var field = typeof(TEnum).GetField(name, BindingFlags.Static | BindingFlags.Public);
            return field.GetCustomAttribute()?.Description ?? name;
        }
    }
    

    The usage would be like this:

    case SortableTypeE.Type:
        var order = EnumHelper.DescriptionOrder((Item x) => x.MyEnum);
        result = sortOrder == SortOrder.TypeE.ASC
            ? items.OrderBy(order)
            : items.OrderByDescending(order);
        result = result.ThenBy(i => i.SomeOtherProperty);
        break;
    

    which would generate expression like this:

    x => x.MyEnum == Enum[0] ? 0 :
         x.MyEnum == Enum[1] ? 1 :
         ...
         x.MyEnum == Enum[N-2] ? N - 2 :
         N - 1;
    

    where 0,1,..N-2 is the corresponding index in the value list sorted by description.

提交回复
热议问题