实现排序属性的最佳实践

时间:2017-09-10 22:43:41

标签: entity-framework linq sorting asp.net-web-api .net-core

我有一个api Get方法,它接受sort属性作为字符串。 在不使用switch语句的情况下处理它的最佳解决方案是什么?

public ActionResult Index(string sortOrder)
{
   var students = from s in db.Students
                  select s;
   switch (sortOrder)
   {
      case "LastName":
         students = students.OrderByDescending(s => s.LastName);
         break;
      case "EnrollmentDate":
         students = students.OrderBy(s => s.EnrollmentDate);
         break;
      case "Birthday":
         students = students.OrderBy(s => s.Birthday);
         break;
      default:
         students = students.OrderBy(s => s.LastName);
         break;
   }
   return View(students.ToList());
}

我在微软的页面上找到了以下代码,但我相信应该有更优雅的方式来实现它。

1 个答案:

答案 0 :(得分:2)

使用以下方法实现灵活排序。该方法需要属性名称和排序方向参数。

public Func<IQueryable<T>, IOrderedQueryable<T>> GetOrderByExpression<T>(string propertyName, bool isDescending = false)
    {
        Type typeQueryable = typeof(IQueryable<T>);
        ParameterExpression argQueryable = System.Linq.Expressions.Expression.Parameter(typeQueryable, "p");
        var outerExpression = System.Linq.Expressions.Expression.Lambda(argQueryable, argQueryable);

        var entityType = typeof(T);
        ParameterExpression arg = System.Linq.Expressions.Expression.Parameter(entityType, "x");

        Expression expression = arg;

        PropertyInfo propertyInfo = entityType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
        expression = System.Linq.Expressions.Expression.Property(expression, propertyInfo);

        LambdaExpression lambda = System.Linq.Expressions.Expression.Lambda(expression, arg);            
        string methodName = isDescending ? "OrderByDescending" : "OrderBy";

        MethodCallExpression resultExp = System.Linq.Expressions.Expression.Call(typeof(Queryable),
                                                                                 methodName,
                                                                                 new Type[] { typeof(T), entityType },
                                                                                 outerExpression.Body,
                                                                                 System.Linq.Expressions.Expression.Quote(lambda));

        var finalLambda = System.Linq.Expressions.Expression.Lambda(resultExp, argQueryable);

        return (Func<IQueryable<T>, IOrderedQueryable<T>>)finalLambda.Compile();
    }

用法:

IQueryable<Student> query = db.Set<Student>();
var orderBy = GetOrderByExpression<Student>(sortOrder, true);

if(orderBy != null){
   query = orderBy(query);
}