Goh*_*har 0 .net lambda expression expression-trees
我已经为 EF 通用存储库创建了一个 orderby 表达式,如下 string command = orderByDesc ? "排序依据降序" : "排序依据";
var type = typeof(T);
var property = type.GetProperty(orderby);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
items.Expression, Expression.Quote(orderByExpression));
items = items.Provider.CreateQuery<T>(resultExpression);
Run Code Online (Sandbox Code Playgroud)
现在我想创建包含 2 列的表达式用于排序,但无法找到有用的内容。
请帮我创建一个包含 2 列的 orderby 表达式。
我不明白接受的答案是如何接受的答案,因为OP询问如何为多列排序场景创建表达式树。
有时,您必须使用表达式树手动构建OrderBy语句,因为您不知道用户想要对哪些列进行排序。例如,当您使用数据表构建网格并且某些列可排序时,用户可以按住 SHIFT 键单击列标题以按多列排序:
屏幕截图显示用户想要按磁带(这是一个string)和插槽号(这是一个double)对网格进行排序。
构建用于排序的表达式树时,棘手的部分是第一次需要使用OrderBy*,但第二次及以后,需要切换到使用ThenBy*。
我将演示如何使用扩展方法来做到这一点IQueryable:
namespace DataTables.AspNet.Core
{
public interface ISort
{
int Order { get; }
SortDirection Direction { get; }
}
public enum SortDirection
{
Ascending = 0,
Descending = 1
}
}
namespace DL.SO.Framework.Mvc.DataTables.Extensions
{
public static class QueryableExtensions
{
public static IQueryable<TModel> OrderByColumns<TModel>(
this IQueryable<TModel> collection,
IDictionary<string, ISort> sortedColumns)
{
// Basically sortedColumns contains the columns user wants to sort by, and
// the sorting direction.
// For my screenshot, the sortedColumns looks like
// [
// { "cassette", { Order = 1, Direction = SortDirection.Ascending } },
// { "slotNumber", { Order = 2, Direction = SortDirection.Ascending } }
// ]
bool firstTime = true;
// The type that represents each row in the table
var itemType = typeof(TModel);
// Name the parameter passed into the lamda "x", of the type TModel
var parameter = Expression.Parameter(itemType, "x");
// Loop through the sorted columns to build the expression tree
foreach (var sortedColumn in sortedColumns.OrderBy(sc => sc.Value.Order))
{
// Get the property from the TModel, based on the key
var prop = Expression.Property(parameter, sortedColumn.Key);
// Build something like x => x.Cassette or x => x.SlotNumber
var exp = Expression.Lamda(prop, parameter);
// Based on the sorting direction, get the right method
string method = String.Empty;
if (firstTime)
{
method = sortedColumn.Value.Direction == SortDirection.Ascending
? "OrderBy"
: "OrderByDescending";
firstTime = false;
}
else
{
method = sortedColumn.Value.Direction == SortDirection.Ascending
? "ThenBy"
: "ThenByDescending";
}
// itemType is the type of the TModel
// exp.Body.Type is the type of the property. Again, for Cassette, it's
// a String. For SlotNumber, it's a Double.
Type[] types = new Type[] { itemType, exp.Body.Type };
// Build the call expression
// It will look something like:
// OrderBy*(x => x.Cassette) or Order*(x => x.SlotNumber)
// ThenBy*(x => x.Cassette) or ThenBy*(x => x.SlotNumber)
var mce = Expression.Call(typeof(Queryable), method, types,
collection.Expression, exp);
// Now you can run the expression against the collection
collection = collection.Provider.CreateQuery<TModel>(mce);
}
return collection;
}
}
}
Run Code Online (Sandbox Code Playgroud)
注:OrderBy* 表示 OrderBy 或 OrderByDescending。ThenBy* 也是如此。
| 归档时间: |
|
| 查看次数: |
1975 次 |
| 最近记录: |