无法使用泛型lambda表达式执行LINQ Where子句
本文关键字:执行 LINQ Where 子句 表达式 lambda 泛型 | 更新日期: 2023-09-27 18:19:33
我正在尝试开发一个通用函数,该函数应用Where子句,但"inputQuery.Where(condition)"语句不编译。我得到"参数2:无法从"System.Linq.Expressions.LambdaExpression"转换为"System.Linq.Expressions.Expression<System.Func<object,bool>>"。
public IQueryable<Object> ExecuteWhereClause(IQueryable<Object> inputQuery, Object typedValue, Type viewType, String paramName, Type paramType)
{
ParameterExpression parameter = Expression.Parameter(viewType);
Type[] typeArgs = { viewType, typeof(bool) };
var condition =
Expression.Lambda(
typeof(Func<,>).MakeGenericType(typeArgs),
Expression.Equal(
Expression.Property(parameter, paramName),
Expression.Constant(typedValue, paramType)
),
parameter
);
return inputQuery.Where(condition);
}
我想您有点混淆了表达式如何与Where
一起工作。
Where函数中的谓词参数具有具体类型
Expression<Func<TSource, bool>> predicate
其中TSource
-冷却中元素的类型,在您的情况下,您有集合IQueryable<Object> inputQuery
,因此TSource
始终是Object
返回值为静态类型-bool
。
所以,即使您以某种方式将通用LambdaExpression
转换为Expression<Func<Object, bool>>
,也会出现错误,因为viewType
可能不是Object
。
这个问题你只需创建类型化的LambdaExpression
就可以解决
var condition =
Expression.Lambda<Func<object,bool>>(
Expression.Equal(
Expression.Property(parameter, paramName),
Expression.Constant(typedValue, paramType)
),
parameter
);
但现在如果viewType
不是Object
,则会出现另一个错误
"类型的ParameterExpression不能用于"System.Object"类型的委托参数
因此,您有几种方法:
首先:不使用viewType
,而是始终使用object
,在这种情况下,当尝试获取属性时会出现另一个错误,因为您只能获取那些具有object
类的属性。
第二:稍微改变一下你的函数,使用通用参数
IQueryable<Object>
->IQueryable<T>
用这个T
创建参数
ParameterExpression parameter = Expression.Parameter(typeof(T));
因为您只能将此类型的参数传递给可用的Where
函数lambda Expression.Lambda<Func<T,bool>>
。
使用Expression.Lambda<Func<T,bool>>
-所以这确实需要Where
-函数来处理源集合中元素类型的可用对象。
所以最后你们可以得到下一个功能:
public static IQueryable<T> ExecuteWhereClause<T>(IQueryable<T> inputQuery, object typedValue, String paramName)
{
ParameterExpression parameter = Expression.Parameter(typeof(T));
var condition =
Expression.Lambda<Func<T,bool>>(
Expression.Equal(
Expression.Property(parameter, paramName),
Expression.Constant(typedValue)
),
parameter
);
return inputQuery.Where(condition);
}
甚至
public static IQueryable<T> ExecuteWhereClause<T,U>(IQueryable<T> inputQuery, U typedValue, String paramName)
{
ParameterExpression parameter = Expression.Parameter(typeof(T));
var condition =
Expression.Lambda<Func<T,bool>>(
Expression.Equal(
Expression.Property(parameter, paramName),
Expression.Constant(typedValue)
),
parameter
);
return inputQuery.Where(condition);
}
您正在构建lambda,它需要viewType,但不能与Object一起使用。如果你想这样做,你必须投
public IQueryable<Object> ExecuteWhereClause(IQueryable<Object> inputQuery, Object typedValue, Type viewType, String paramName, Type paramType)
{
ParameterExpression parameter = Expression.Parameter(typeof(Object));
var condition =
Expression.Lambda<Func<Object, bool>>(
Expression.Equal(
Expression.Property(Expression.Convert(parameter, viewType), paramName),
Expression.Constant(typedValue, paramType)
),
parameter
);
return inputQuery.Where(condition);
}