我如何加入像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);
答案 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);