Pic*_*ick 17 c# linq lambda expression
我有两个lambda表达式:
__CODE__
和
Expression<Func<MyEntity, bool>> e1 = i = >i.FName.Contain("john");
Run Code Online (Sandbox Code Playgroud)
i类型来自我的poco实体,不能用于调用.我想在运行时结合这些.
我想在运行时以类似的方式组合这些表达式:
Expression<Func<MyEntity, bool>> e2 = i => i.LName.Contain("smith");
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 51
问题是你不能只是"和"/"或"它们,因为你需要重新编写内部来改变参数; 如果你使用.Body的e1,但参数从e2,它不会工作-因为.Body中e1引用未定义一个完全无关的参数实例.如果您使用以下内容,则更为明显:
Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = j => j.LName.Contains("smith");
Run Code Online (Sandbox Code Playgroud)
(注意e1使用i和e2使用之间的区别j)
如果我们在不重写参数的情况下组合它们,我们就会得到荒谬的:
Expression<Func<MyEntity, bool>> combined =
i => i.FName.Contains("john") && j.LName.Contains("smith");
Run Code Online (Sandbox Code Playgroud)
(哇...... j来自哪里?)
然而; 无论参数的名称如何,问题都是相同的:它仍然是一个不同的参数.
因为表达式是不可变的,所以你不能只是"就地"交换它.
诀窍是使用"访问者"来重写节点,如下所示:
using System;
using System.Linq.Expressions;
class SwapVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public SwapVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
static class Program
{
static void Main()
{
Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = i => i.LName.Contains("smith");
// rewrite e1, using the parameter from e2; "&&"
var lambda1 = Expression.Lambda<Func<MyEntity, bool>>(Expression.AndAlso(
new SwapVisitor(e1.Parameters[0], e2.Parameters[0]).Visit(e1.Body),
e2.Body), e2.Parameters);
// rewrite e1, using the parameter from e2; "||"
var lambda2 = Expression.Lambda<Func<MyEntity, bool>>(Expression.OrElse(
new SwapVisitor(e1.Parameters[0], e2.Parameters[0]).Visit(e1.Body),
e2.Body), e2.Parameters);
}
}
Run Code Online (Sandbox Code Playgroud)