2

I have the next class structure:

    public class Order
    {
        public User User { get; set; }
        public string Name { get; set; }
    }

    public class Authentication
    {
        public string Email { get; set; }      
    }

    public class User
    {
        public string Name { get; set; }
        public List<Authentication> Auths { get; set; }
    }

I'm trying to build an expression at runtime to search entities by User.Name, Order.Name or User.Auths.Email

There are three expressions I'm trying to combine:

    Expression<Func<Order, bool>> usernameExpression = order => order.Name.Contains(searchValue);
    Expression<Func<Order, bool>> nameExpression = order => order.User.Name.Contains(searchValue);
    Expression<Func<Order, bool>> emailExpression = order => order.User.Auths.Any(auth => auth.Email.Contains(searchValue));

I successfully combined two first expressions using ParameterReplacer from this thread: How to Combine two lambdas

However, when combining resulting expression with email expression I get the next error:

Property 'System.String Email' is not defined for type Order'

Looks like the scope doesn't know anything about inner 'auth' parameter. Is it possible to creeate the expression without rebuilding it from scratch?

4
  • Post your attempt at the combination Commented Apr 15, 2016 at 15:49
  • You say that you want to combine the, but how do you want to combine them? What expression are you trying to end up with? Commented Apr 15, 2016 at 15:55
  • @Servy, I was trying to combine them using OrAlso\AndAlso clause. The link to the helper from Ivan's post resolved the issue Commented Apr 15, 2016 at 16:18
  • @Refraction That doesn't answer the question of how, specifically, you want to combine them, and what, exactly, you want the examples you provided to produce. Commented Apr 15, 2016 at 16:37

1 Answer 1

7

The ParameterReplacer you have used is too simplified and blindly replaces every parameter.

Use this instead:

public static class ExpressionUtils
{
    public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
    {
        return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
    }

    class ParameterReplacer : ExpressionVisitor
    {
        public ParameterExpression Source;
        public Expression Target;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == Source ? Target : base.VisitParameter(node);
        }
    }
}

Or use this or this predicate builder helpers.

Sign up to request clarification or add additional context in comments.

2 Comments

expression helper from the first link perfectly fixed the issue. Thank you
@infinitesimal Something like in here stackoverflow.com/a/69470727/5202563

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.