Если я правильно понимаю, у вас есть LambdaExpression
вместо Expression<Func<T, bool>>
и вы хотите использовать его как Where
но на IQueryable
(который DbSet
класс орудий), а не IQueryable<T>
.
Все, что вам нужно знать, это то, что методы расширения IQueryable<T>
просто испускают MethodCallExpression
соответствующему методу Queryable
в дереве выражений запроса.
Например, чтобы эмулировать Where
или Select
на IQueryable
вы можете использовать следующие методы пользовательских расширений:
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
методов, необходимых.
Update: Поскольку вы интересны, вот пример использования выражения прототипов, чтобы получить общее определение метода и построить обобщенный метод из него:
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);
}
}
Как создать 'Expression > 'если вы не знаете' T'? –
@IvanStoev Вы можете создавать выражения с использованием типов. – oscilatingcretin
Как не общий термин 'Expression.Lambda', который возвращает' LambdaExpression'? И вы хотите привязать его к 'Where'? –