将表达式树作为参数传递给EntityDataModel中的另一个表达式树

时间:2012-04-25 14:21:19

标签: c# linq lambda

我有两个这样定义的表达式树:

Expression<Func<string, bool>> BoolExpression { get; }

Expression<Func<Customer, string>> PropertyExpression { get; }

我需要创建一个新的表达式树,它将产生相当于:

Customer c = null;
var expression = e1(e2(c));

我可以使用Compile(),Invoke():

来完成
Customers c = null;
var e3 = e1.Compile().Invoke(e2.Compile().Invoke(c));

但是我不能使用Compile或Invoke方法,因为我正在使用EntityDataModel。当我将“表达式”传递给Where方法时,它将转换为SQL查询并传递给数据库。

P.S。:我想使用EntityDataModel做一些Query构建器。有n场和m条件。我想为条件定义字段和m表达式的n表达式,然后将它们组合起来。

1 个答案:

答案 0 :(得分:0)

选项1

首先尝试一下 - 我只是尝试使用LINQ-to-SQL,它可以工作,所以它应该在EF中工作。它不是你所拥有的一百万英里,只是说调用e1调用e2的结果:

var e3 = Expression.Lambda<Func<Customer, bool>>(Expression.Invoke(e1, Expression.Invoke(e2, e2.Parameters)), e2.Parameters);

选项2

我以为你需要遍历表达式树并替换BoolExpression函数中String参数的用法,如下所示:

// replace parameter use anywhere in e1.Body with e2.Body
var remover = new ParameterReplaceVisitor(e2.Body);
var bb = remover.Visit(e1.Body);

// create a new lambda with our amended body but still with e2 parameters i.e. the Customer
var e3 = Expression.Lambda<Func<Customer, bool>>(bb, e2.Parameters);

public class ParameterReplaceVisitor : ExpressionVisitor
{
    Expression _replace;

    public ParameterReplaceVisitor(Expression replace)
    {
        _replace = replace;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        // when we encounter a parameter replace it
        return _replace;
    }
}

显然,如果在表达式中引入多个参数,事情就会变得复杂一些。