C# 连接lambda表达式

C# 连接lambda表达式,c#,lambda,C#,Lambda,我如何连接两个lambda表达式,如theese: Expression<Func<string, bool>> expr1 = a => a.Length > 100; Expression<Func<string, bool>> expr2 = b => b.Length < 200; 表达式expr1=a=>a.长度>100; 表达式expr2=b=>b.长度s.Lengtha.长度>100; 表达式expr2=b=

我如何连接两个lambda表达式,如theese:

Expression<Func<string, bool>> expr1 = a => a.Length > 100;
Expression<Func<string, bool>> expr2 = b => b.Length < 200;
表达式expr1=a=>a.长度>100;
表达式expr2=b=>b.长度<200;
。。。变成这样一个表达式:

Expression<Func<string, bool>> expr3 = s => s.Length < 100 && s.Length < 200;
表达式expr3=s=>s.Length<100和&s.Length<200;
也就是说,用一个AndAlso操作符连接它们。(或与此相关的任何其他运营商…)

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

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

expr3=c=>expr1(a)和&expr2(b);
如果您与普通代理打交道,您的“类似”功能将起作用。 但如果必须使用表达式树,我看不到除了递归替换之外的任何其他解决方案

在.NET 4中,您可以使用System.Linq.Expressions.ExpressionVisitor使这种递归替换更容易。对于.NET 3.5,请查看以下示例:

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


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

我刚刚发现如何使用新的更新方法对.NET 4执行此操作。既然这是一种新方法,我想他们一定也需要它。我真的很高兴,因为med.NET3.5解决方案真的很难看。 (注意:此解决方案无论如何都不起作用。请检查注释。)

表达式expr1=a=>a.长度>100;
表达式expr2=b=>b.长度<200;
//这将生成一个新表达式,其中参数b替换为a
expr2=expr2.Update(expr1.Body,expr1.Parameters);
//现在我们可以连接这些实体并生成一个新的lambda表达式。
表达式expr3=Expression.Lambda(Expression.AndAlso(expr1.Body,expr2.Body),expr1.Parameters);

表达式还不错。调用…:

    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);
var strings=(新[]{“a”、“bb”、“ccc”、“dddd”、“eeeee”、“fffff”});
表达式expr1=a=>a.Length>1;
表达式expr2=b=>b.长度<4;
ParameterExpression p=expr1.参数[0];
var andAlso=System.Linq.Expressions.Expression.andAlso(Expression.Invoke(expr1,p),Expression.Invoke(expr2,p));
var lambda=LambdaExpression.lambda(andAlso,p);
var filteredStrings=strings.AsQueryable().Where(lambda);

只是想知道,为什么不能使用表达式expr3=s=>s.Length<100和&s.Length<200;?这是因为表达式是根据系统中的设置生成的。实际上,我需要将一个表达式列表加入到最后一个表达式中。我想您误解了更新的作用。它只创建一个具有相同类型、名称和tailcall选项但具有不同主体和参数集的新LambdaExpression。它不会在lamdba主体内进行任何更换。运行示例代码会为expr3输出“a=>((a.Length>100)和(a.Length>100)),这不是您想要的。遗憾的是,您是对的Daniel。。。因此,我回到了我讨厌的解决方案:-(感谢Richard的建议。我将研究这个想法。因为我将表达式转换为SQL(以及其他内容)我需要在我的系统中的多个地方支持InvokeExpression。它比我目前的解决方案更好…我刚刚意识到这可以帮助我解决一个我刚才遇到的问题,并且完全坚持下去了…干杯!我刚刚检查了ExpressionVisitor,它在这方面做得很好。迫不及待地等待4.0发布。
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);
    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);