【问题标题】:How to convert LambdaExpression to Expression<Func<T,bool>> in C#如何在 C# 中将 LambdaExpression 转换为 Expression<Func<T,bool>>
【发布时间】:2020-04-08 17:52:19
【问题描述】:

我有以下代码在运行时根据我的SearchTerm 输入生成LambdaExpression。我正在尝试构建一个动态的where 子句。但是我被困在如何从LambdaExpression 转换为Expression&lt;Func&lt;T,bool&gt;&gt;

private static Expression<Func<T,bool>> GetSearchAppliedQuery(IEnumerable<SearchTerm> terms)
{
    var parameterExpression = ExpressionHelper.Parameter<T>();
    Expression finalExpression = Expression.Constant(true);
    Expression subExpression = Expression.Constant(false);

    // Build up the LINQ Expression backwards:
    // query = query.Where(x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value"));

    foreach (var term in terms)
    {
        var hasMultipleTerms = term.EntityName?.Contains(',') ?? false;

        if (hasMultipleTerms)
        {
            var entityTerms = term.EntityName.Split(',');

            foreach (var entityTerm in entityTerms)
            {
                term.EntityName = entityTerm;

                // x => x.Property == "Value" || x.AnotherProperty == "Value"
                subExpression = Expression.OrElse(subExpression, GetComparisonExpression(term, parameterExpression));
            }
        }

        // x => x.Property == "Value" && x.AnotherProperty == "Value"
        finalExpression = Expression.AndAlso(finalExpression, hasMultipleTerms ? subExpression : GetComparisonExpression(term, parameterExpression));
    }

    // x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value")
    var lambdaExpression = ExpressionHelper.GetLambda<T, bool>(parameterExpression, finalExpression);

    // How to do this conversion??
    Expression<Func<T,bool>> returnValue = ..??;

    return returnValue;
}

我正在尝试应用上述方法的结果来获取查询,如下所示:

public static IQueryable<T> GetQuery(IQueryable<T> inputQuery, ISpecification<T> specification)
{
    var query = inputQuery;

    // modify the IQueryable using the specification's criteria expression
    if (specification.Criteria != null)
    {
        query = query.Where(specification.Criteria);
    }

    ...
    return query;
}

所以我的最终查询看起来像,

query = query.Where(x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value"))

Edit-1: 根据@Ivan Stoev 的要求添加ExpressionHelper.GetLambda 方法

public static class ExpressionHelper
{
    public static LambdaExpression GetLambda<TSource, TDest>(ParameterExpression obj, Expression arg)
    {
        return GetLambda(typeof(TSource), typeof(TDest), obj, arg);
    }

    public static LambdaExpression GetLambda(Type source, Type dest, ParameterExpression obj, Expression arg)
    {
        var lambdaBuilder = GetLambdaFuncBuilder(source, dest);
        return (LambdaExpression)lambdaBuilder.Invoke(null, new object[] { arg, new[] { obj } });
    }

    private static MethodInfo GetLambdaFuncBuilder(Type source, Type dest)
    {
        var predicateType = typeof(Func<,>).MakeGenericType(source, dest);
        return LambdaMethod.MakeGenericMethod(predicateType);
    }
}

我是否遗漏了一些非常基本的东西或做错了什么?请帮忙。

【问题讨论】:

  • 什么是ExpressionHelper.GetLambda 方法?我们能看到吗?
  • 在Edit - 1中添加ExpressionHelper.GetLambda等方法

标签: c# lambda expression-trees iqueryable predicatebuilder


【解决方案1】:

用于获取 lambda 表达式的 ExpressionHelper.GetLambda&lt;T, bool&gt; 方法隐藏了它的实际类型,即所需的 Expression&lt;Func&lt;T, bool&gt;&gt;,因此您只需要使用强制转换运算符即可:

return (Expression<Func<T, bool>>)lambdaExpression;

或者更好,要么将 ExpressionHelper.GetLambda&lt;TSource, TDest&gt; 的结果类型更改为 Expression&lt;Func&lt;TSource, TDest&gt;&gt;,要么不使用该辅助方法 - 如果您在编译时知道泛型类型参数,则只需使用泛型 Expression.Lambda 方法即可(ExpressionHelper.GetLambda&lt;TSource, TDest&gt; 似乎等同于Expression.Lambda&lt;Func&lt;TSource, TDest&gt;&gt;),例如

var lambdaExpression = Expression.Lambda<Func<T, bool>>(parameterExpression, finalExpression);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    相关资源
    最近更新 更多