【发布时间】:2016-12-27 06:20:18
【问题描述】:
是否可以通过调用OrderBy 和Where 创建可重用的LINQ 查询表达式,而不将其应用于特定的IQueryable?
我希望能够做这样的事情:
var data = new List<PlayerDTO>();
var builder = new Builder<PlayerDTO>();
var query = builder.GetQuery();
var results = data.AsQueryable().Provider.CreateQuery(query);
如果不将 IQueryable 对象提供给 GetQuery 方法,我将无法正常工作。
这是我目前的代码:
public Expression GetQuery()
{
var type = typeof(T); // T is PlayerDTO
var col = type.GetProperty(OrderBy.Column);
var orderByMethod = typeof(Queryable).GetMethods().Single(
method => method.Name == "OrderBy"
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2);
var genericOrdebyMethod = orderByMethod.MakeGenericMethod(typeof(T), col.PropertyType);
var parameter = Expression.Parameter(typeof(T), "p"); // {p}
var property = Expression.Property(parameter, col); // {p.ID}
var lambda = Expression.Lambda<Func<T, int>>(property, parameter); // {p => p.ID}
//This list should not exist here
var tempList = new List<PlayerDTO>() { new PlayerDTO(1, "First"), new PlayerDTO(2, "Second") };
var orderByMethodExpression = Expression.Call(genericOrdebyMethod, tempList.AsQueryable().Expression, lambda); // {tempList.OrderBy(p => p.ID)}
var results = tempList.AsQueryable().Provider.CreateQuery(orderByMethodExpression);
return orderByMethodExpression;
}
相关部分是对Expression.Call 的调用,我必须在其中提供IQueryable 才能工作,但我希望能够在不指定现有IQueryable 的情况下构建表达式。
这可能吗?
编辑:
现在我考虑到这一点,实际上我根本不需要这样做......将 IQueryable 作为参数发送给 GetQuery 方法是非常有意义的。不过,我会继续提出这个问题。
【问题讨论】:
-
你不能用
Expression<Func<PlayerDTO,object>> = p => p.ColumnName;吗?您可以在OrderBy方法中使用该表达式。如果您的PlayerDTO实现了一些接口来了解 columnName 属性,这将起作用。否则,您仍然可以仅对属性使用反射。 -
是的,我可以,但我的主要问题是我想包含在表达式中的 OrderBy/Where/etc 类型方法,然后在多个 IQueryables 上重用。
-
只是你在做什么有点奇怪,动态构建一个表达式,使用Provider将它变成一个iQueryable,而你事先知道你将使用哪个属性和哪个方法。
IQueryable上的 Linq 扩展方法实际上与您现在尝试手动执行的操作完全相同(请参阅 this link)。 -
我不确定我是否完全理解.. 我要订购列表的属性仅在运行时才知道。然后基于该属性,我想用一些过滤器构建一个 OrderBy 表达式并从方法中返回它。我会用我正在尝试做的事情来更新我的问题!
-
哦,在这种情况下,我会创建一个扩展方法,它接受
IQueryable<T>并返回IQueryable<T>,这样会更有意义。例如:var result = data.AsQueryable().ModifyQuery();
标签: c# linq expression-trees dynamic-linq