如何使用表达式树为PLINQ构建动态查询
我想为PLINQ定制定制的OrderBy,但我不知道该怎么做.
I want to bild customized OrderBy for PLINQ, but I don't know how to.
对于IQueryable,使用可以使用以下代码:
For IQueryable, use can use below code:
public static class QueryableExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortProperty, ListSortDirection sortOrder)
{
var type = typeof(T);
var property = type.GetProperty(sortProperty);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
var typeArguments = new Type[] { type, property.PropertyType };
var methodName = sortOrder == ListSortDirection.Ascending ? "OrderBy" : "OrderByDescending";
var resultExp = Expression.Call(typeof(Queryable), methodName, typeArguments, source.Expression, Expression.Quote(orderByExp));
return source.Provider.CreateQuery<T>(resultExp);
}
}
但是对于ParallelQuery,没有这样的属性Provider和Expresss.有人知道怎么做吗?
But for ParallelQuery, there's no such property Provider and Expresss. Does anybody know how to do?
public static class QueryableExtensions
{
public static ParallelQuery<T> OrderBy<T>(this ParallelQuery<T> source, string sortProperty, ListSortDirection sortOrder)
{
...
}
}
使用 IQueryable
,您不需要 Provider
,就足以创建表达式并然后直接调用 OrderBy
/ OrderByDescending
.唯一的问题是 OrderBy()
在sorting属性的类型中是通用的,您不知道(不是静态的).
With IQueryable
, you don't need Provider
for this, it's enough to create the expression and then directly call OrderBy
/OrderByDescending
. The only problem is that OrderBy()
is generic in the type of the sorting property, which you don't know (not statically).
您可以通过使用反射调用 OrderBy()
来解决此问题.或者您可以使用 dynamic
:
You can work around that by invoking OrderBy()
using reflection. Or you can use dynamic
:
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortProperty, ListSortDirection sortOrder)
{
var type = typeof(T);
var property = type.GetProperty(sortProperty);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
if (sortOrder == ListSortDirection.Ascending)
{
return Queryable.OrderBy(source, (dynamic)orderByExp);
}
else
{
return Queryable.OrderByDescending(source, (dynamic)orderByExp);
}
}
您可以对PLINQ完全使用它:
And you can use exactly the same with PLINQ:
public static ParallelQuery<T> OrderBy<T>(this ParallelQuery<T> source, string sortProperty, ListSortDirection sortOrder)
{
var type = typeof(T);
var property = type.GetProperty(sortProperty);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByFunc = Expression.Lambda(propertyAccess, parameter).Compile();
if (sortOrder == ListSortDirection.Ascending)
{
return ParallelEnumerable.OrderBy(source, (dynamic)orderByFunc);
}
else
{
return ParallelEnumerable.OrderByDescending(source, (dynamic)orderByFunc);
}
}