无法使用通用lambda表达式执行LINQ Where子句

时间:2015-10-27 03:05:52

标签: c# linq lambda where

我正在尝试开发一个应用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);
    }

2 个答案:

答案 0 :(得分:0)

您正在构建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);
}

答案 1 :(得分:0)

我觉得你对Where的表达方式有点困惑。

Where funtcion中的

谓词参数具体类型

Expression<Func<TSource, bool>> predicate

其中TSource - 在coolection中的元素类型,在您的情况下,您有集合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> - &gt; IQueryable<T>

使用此T

创建参数
ParameterExpression parameter = Expression.Parameter(typeof(T));

因为您只能将此类型的参数传递给可用Expression.Lambda<Func<T,bool>>函数的lambda Where

使用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);
}