如果我理解正確的話,你有LambdaExpression
,而不是Expression<Func<T, bool>>
,你想用它作爲Where
但IQueryable
(其中DbSet
類實現),而不是IQueryable<T>
。
您只需要知道IQueryable<T>
擴展方法只需將MethodCallExpression
發送到查詢表達式樹中對應的Queryable
方法即可。
例如,要效仿IQueryable
Where
或Select
您可以使用下面的自定義擴展方法:
public static class QueryableExtensions
{
public static IQueryable Where(this IQueryable source, LambdaExpression predicate)
{
var expression = Expression.Call(
typeof(Queryable), "Where",
new Type[] { source.ElementType },
source.Expression, Expression.Quote(predicate));
return source.Provider.CreateQuery(expression);
}
public static IQueryable Select(this IQueryable source, LambdaExpression selector)
{
var expression = Expression.Call(
typeof(Queryable), "Select",
new Type[] { source.ElementType, selector.Body.Type },
source.Expression, Expression.Quote(selector));
return source.Provider.CreateQuery(expression);
}
}
你可以做需要的其他Queryable
方法類似。
更新:既然你是在有趣,這裏是一個使用表達式的原型獲得泛型方法定義,並從它構建的通用方法的一個例子:
public static class QueryableExtensions
{
static MethodInfo QueryableMethod<T>(this Expression<Func<IQueryable<object>, T>> prototype, params Type[] types)
{
return ((MethodCallExpression)prototype.Body).Method
.GetGenericMethodDefinition()
.MakeGenericMethod(types);
}
public static IQueryable Where(this IQueryable source, LambdaExpression predicate)
{
var expression = Expression.Call(
QueryableMethod(q => q.Where(x => true), source.ElementType),
source.Expression, Expression.Quote(predicate));
return source.Provider.CreateQuery(expression);
}
public static IQueryable Select(this IQueryable source, LambdaExpression selector)
{
var expression = Expression.Call(
QueryableMethod(q => q.Select(x => 1), source.ElementType, selector.Body.Type),
source.Expression, Expression.Quote(selector));
return source.Provider.CreateQuery(expression);
}
}
如何創建'表達 >'如果你不知道'T'? –
@IvanStoev您可以使用類型創建表達式。 – oscilatingcretin
像返回'LambdaExpression'的非泛型'Expression.Lambda'?你想將它綁定到「Where」? –