我正在努力实现这种转换
"Address.Street" => (p) => p.Address.Street "Name" => (p) => p.Name
我能够找到一种使用反射使用表达式生成订单的方法,但是Address.Street由于适用于单个属性级别,因此它不适用于复杂的排序。
Address.Street
有没有办法做到这一点?我已经看到我编译了lambda表达式,但是我不明白如何使它适用于这种情况。
创建表达式并不难,但是棘手的部分是当您不知道属性的类型(因此选择器表达式结果的类型)时如何将其绑定到相应的OrderBy(Descending)/ ThenBy(Descendig)方法。
OrderBy(Descending)
ThenBy(Descendig)
这是封装在自定义扩展方法中的所有内容:
public static partial class QueryableExtensions { public static IOrderedQueryable<T> OrderByMember<T>(this IQueryable<T> source, string memberPath) { return source.OrderByMemberUsing(memberPath, "OrderBy"); } public static IOrderedQueryable<T> OrderByMemberDescending<T>(this IQueryable<T> source, string memberPath) { return source.OrderByMemberUsing(memberPath, "OrderByDescending"); } public static IOrderedQueryable<T> ThenByMember<T>(this IOrderedQueryable<T> source, string memberPath) { return source.OrderByMemberUsing(memberPath, "ThenBy"); } public static IOrderedQueryable<T> ThenByMemberDescending<T>(this IOrderedQueryable<T> source, string memberPath) { return source.OrderByMemberUsing(memberPath, "ThenByDescending"); } private static IOrderedQueryable<T> OrderByMemberUsing<T>(this IQueryable<T> source, string memberPath, string method) { var parameter = Expression.Parameter(typeof(T), "item"); var member = memberPath.Split('.') .Aggregate((Expression)parameter, Expression.PropertyOrField); var keySelector = Expression.Lambda(member, parameter); var methodCall = Expression.Call( typeof(Queryable), method, new[] { parameter.Type, member.Type }, source.Expression, Expression.Quote(keySelector)); return (IOrderedQueryable<T>)source.Provider.CreateQuery(methodCall); }