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