加入lambda表达式

时间:2010-03-01 18:46:20

标签: c# lambda

我如何加入像theese这样的两个lambda表达式:

Expression<Func<string, bool>> expr1 = a => a.Length > 100;
Expression<Func<string, bool>> expr2 = b => b.Length < 200;

...变成这样的表达式:

Expression<Func<string, bool>> expr3 = s => s.Length < 100 && s.Length < 200;

即,将它们与AndAlso运算符连接起来。 (或任何其他运营商......)

我实际上成功地进行了一些讨厌的递归替换lambda参数,然后加入了Expression.AndAlso方法。但我正在寻找更简单的东西。

例如:(显然不起作用。)

Expression<Func<string, bool>> expr3 = c => expr1(a) && expr2(b);

3 个答案:

答案 0 :(得分:2)

如果您正在与普通代表​​打交道,那么“类似”会起作用。 但是如果你必须使用表达式树,我没有看到任何其他解决方案而不是递归替换。

在.NET 4中,您可以使用System.Linq.Expressions.ExpressionVisitor使这种递归替换变得更加容易。对于.NET 3.5,请查看此示例:http://msdn.microsoft.com/en-us/library/bb882521.aspx

使用ExpressionVisitor,您只需覆盖要替换的节点类型的方法,并自动重建周围的树。

如果您正在处理与LINQ一起使用的条件,那么动态组合条件的更简单的解决方案就是多次调用Where()。

答案 1 :(得分:2)

Expression.Invoke ......:

并不算太糟糕
    var strings = (new [] { "a", "bb", "ccc", "dddd", "eeeee", "fffff" });
Expression<Func<string, bool>> expr1 = a => a.Length > 1; 
Expression<Func<string, bool>> expr2 = b => b.Length < 4;

ParameterExpression p = expr1.Parameters[0];

var andAlso = System.Linq.Expressions.Expression.AndAlso(Expression.Invoke(expr1, p), Expression.Invoke(expr2, p)); 
var lambda = LambdaExpression.Lambda<Func<string, bool>>(andAlso, p);
var filteredStrings = strings.AsQueryable().Where(lambda);

答案 2 :(得分:1)

我刚刚发现如何使用新的Update方法在.NET 4中执行此操作。由于这是一种新方法,我认为他们也必须使用它。我真的很高兴,因为med .NET 3.5解决方案真的很难看。 (注意:此解决方案无论如何都不起作用。请检查注释。)

Expression<Func<string, bool>> expr1 = a => a.Length > 100;
Expression<Func<string, bool>> expr2 = b => b.Length < 200;

// This produces a new expression where the parameter b is replaced with a
expr2 = expr2.Update(expr1.Body, expr1.Parameters);

// So now we can join the bodies and produce a new lambda expression.
Expression<Func<string, bool>> expr3 = Expression.Lambda<Func<string, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);