【问题标题】:Unable to execute LINQ Where clause with generic lambda expression无法使用通用 lambda 表达式执行 LINQ Where 子句
【发布时间】:2015-10-27 03:05:51
【问题描述】:

我正在尝试开发一个应用 Where 子句但“inputQuery.Where(condition)”语句无法编译的通用函数。我得到“参数 2:无法从 'System.Linq.Expressions.LambdaExpression' 转换为 'System.Linq.Expressions.Expression>'。

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

【问题讨论】:

  • 为什么你扩展 IQueryable&lt;Object&gt; 而不是 IQueryable&lt;T&gt;?在你的情况下,你可以Expression.Lambda&lt;Func&lt;object,bool&gt;( Expression.Equal( Expression.Property(parameter, paramName), Expression.Constant(typedValue, paramType) ), parameter)

标签: c# linq lambda where


【解决方案1】:

我认为您对 Where 的表达式如何工作感到有些困惑。

谓词 Where 函数中的参数有具体类型

Expression<Func<TSource, bool>> predicate

其中TSource - 冷却中元素的类型,在你的情况下你有集合IQueryable&lt;Object&gt; inputQuery 所以TSource 总是Object

返回值的静态类型 - bool

因此,即使您以某种方式将通用 LambdaExpression 转换为 Expression&lt;Func&lt;Object, bool&gt;&gt; 也会出错,因为 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&lt;Object&gt; -> IQueryable&lt;T&gt;

用这个T创建参数

ParameterExpression parameter = Expression.Parameter(typeof(T));

因为您只能将这种类型的参数传递给 lambda Expression.Lambda&lt;Func&lt;T,bool&gt;&gt; 可用的 Where 函数。

使用Expression.Lambda&lt;Func&lt;T,bool&gt;&gt; - 所以这确实需要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);
}

【讨论】:

    【解决方案2】:

    您正在构建需要 viewType 的 lambda,它不能与 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-06
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      相关资源
      最近更新 更多