Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不使用Invoke方法的情况下组合两个lambda表达式?_C#_Linq_Lambda_Expression - Fatal编程技术网

C# 如何在不使用Invoke方法的情况下组合两个lambda表达式?

C# 如何在不使用Invoke方法的情况下组合两个lambda表达式?,c#,linq,lambda,expression,C#,Linq,Lambda,Expression,我有两个lambda表达式: Expression<Func<MyEntity, bool>> e1 = i = >i.FName.Contain("john"); 表达式e1=i=>i.FName.Contain(“john”); 及 表达式e2=i=>i.LName.Contain(“史密斯”); i类型来自我的poco实体,不能与invoke一起使用。我想在运行时结合这些 我希望在运行时以类似的方式组合这些表达式: Expression<Func&

我有两个lambda表达式:

Expression<Func<MyEntity, bool>> e1 = i = >i.FName.Contain("john");
表达式e1=i=>i.FName.Contain(“john”); 及

表达式e2=i=>i.LName.Contain(“史密斯”); i类型来自我的poco实体,不能与invoke一起使用。我想在运行时结合这些

我希望在运行时以类似的方式组合这些表达式:

Expression<Func<MyEntity, bool>> e3 = Combine(e1,e2);
表达式e3=组合(e1,e2);
问题在于,您不能只是“和”/“或”它们,因为您需要重新编写内部代码来更改参数;如果使用
e1
中的
.Body
,但使用
e2
中的参数,则该参数将不起作用-因为
e1
.Body
引用了未定义的完全无关的参数实例。如果您使用:

Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = j => j.LName.Contains("smith");
(哇……
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);
    }
}
使用系统;
使用System.Linq.Expressions;
类SwapVisitor:ExpressionVisitor
{
私有只读表达式from、to;
公共SwapVisitor(表达式from,表达式to)
{
this.from=from;
这个;
}
公共重写表达式访问(表达式节点)
{
返回节点==从?到:基本访问(节点);
}
}
静态类程序
{
静态void Main()
{
表达式e1=i=>i.FName.Contains(“john”);
表达式e2=i=>i.LName.Contains(“smith”);
//使用e2中的参数重写e1;&&&
var lambda1=Expression.Lambda(Expression.AndAlso(
新SwapVisitor(e1.参数[0],e2.参数[0])。访问(e1.主体),
e2.主体),e2.参数);
//使用e2中的参数重写e1;“||”
var lambda2=Expression.Lambda(Expression.OrElse(
新SwapVisitor(e1.参数[0],e2.参数[0])。访问(e1.主体),
e2.主体),e2.参数);
}
}

是否可以使用简单的if语句

using (MyDataBaseEntities db = new MyDataBaseEntities())
{
if (db.People.Any(p => p.FirstName == FirstNameText.Text && p.LastName == LastNameText.Text))
    {
        //Do something
    }
}    

是的,还有。我想在运行时将它们结合起来。答案很好!花了两天的时间来实现这个,其他答案包含了大量的代码。非常感谢,马克!
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);
    }
}
using (MyDataBaseEntities db = new MyDataBaseEntities())
{
if (db.People.Any(p => p.FirstName == FirstNameText.Text && p.LastName == LastNameText.Text))
    {
        //Do something
    }
}