簡體   English   中英

如何在不使用 Invoke 方法的情況下組合兩個 lambda 表達式?

[英]How can I combine two lambda expressions without using Invoke method?

我有兩個 lambda 表達式:

Expression<Func<MyEntity, bool>> e1 = i = >i.FName.Contain("john");

Expression<Func<MyEntity, bool>> e2 = i => i.LName.Contain("smith");

i 類型來自我的 poco 實體,不能與 invoke 一起使用。 我想在運行時結合這些。

我想在運行時以類似的方式組合這些表達式:

Expression<Func<MyEntity, bool>> e3 = Combine(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");

(注意使用i e1和使用j e2之間的區別)

如果我們在不重寫參數的情況下組合它們,我們會得到無意義的:

Expression<Func<MyEntity, bool>> combined =
         i => i.FName.Contains("john") && 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);
    }
}

也許用一個簡單的 if 語句?

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM