Вопрос по c#, linq – Как я могу объединить два лямбда-выражения без использования метода Invoke?

15

У меня есть два лямбда-выражения:

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);
скомбинироватьhow - "а также" ? Marc Gravell♦
да и тоже. Я хочу объединить их во время выполнения. PickleRick

Ваш Ответ

2   ответа
0
using (MyDataBaseEntities db = new MyDataBaseEntities())
    {
            {
                if (db.People.Any(p => p.FirstName == FirstNameText.Text && p.LastName == LastNameText.Text))
                            {
                                 //Do something
                            }
            }      
    }

Может быть, с простым выражением if?

Кстати, я новичок, извините, если мой ответ глупый.

46

Проблема состоит в том, что вы не можете просто "и" / "или" их, потому что вам нужно переписать внутренности, чтобы изменить параметры; если вы используете.Body отe1, ноparameter отe2это не сработает - потому что.Body изe1 ссылается на совершенно не связанный экземпляр параметра, который не определен. Это большеobvious если вы используете:

Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = j => j.LName.Contains("smith");

(обратите внимание на разницу междуe1 с помощьюi а такжеe2 с помощьюj)

Если мы объединим их без переписывания параметра, мы получим бессмысленное:

Expression<Func<MyEntity, bool>> combined =
         i => i.FName.Contains("john") && j.LName.Contains("smith");

(воу .... где жеj родом из?)

ТЕМ НЕ МЕНИЕ; проблема идентична независимо отname параметра: это все еще другой параметр.

А так как выражение является неизменным, вы не можете просто поменять его местами.

Хитрость заключается в том, чтобы использовать «посетителя»; переписать узлы, вот так:

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);
    }
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded PickleRick

Похожие вопросы