Convert 2 arguments Lambda expression to 1 argument Lambda expression (with one argument)

I have an expression

Expression<Func<Car, Driver, bool>> CanBeDrivenBy = (car, driver) => car.Category == 'B' && driver.Age > 18; 

and I want to get cars that can be driven by some kind of driver

 IQueryable<Cars> cars = ...; Driver driver = ...; cars.Where(CanBeDrivenBy); // Fail, expecting Expression<Func<Car, bool>> 

Therefore, I need to convert Expression<Func<Car, Driver, bool>> to Expression<Func<Car, bool>> (specify the driver)

Yes i can use

 cars.Where(c => c.Category == 'B' && driver.Age > 18); 

but I need a solution with an expression that can be changed dynamically. And I need to pass Expression (using entity infrastructure)

+4
source share
2 answers

It works

I wrote this function to reduce the number of arguments from 2 to 1, specifying the second argument.

 public static Expression<Func<T1, TResult>> Bind2nd<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> source, T2 argument) { Expression arg2 = Expression.Constant(argument, typeof(T2)); var arg1 = Expression.Parameter(typeof(T1)); return Expression.Lambda<Func<T1, TResult>>(Expression.Invoke(source, arg1, arg2), arg1); } 

and use

 IQueryable<Cars> cars = ...; Driver driver = ...; cars.Where(Bind2nd(CanBeDrivenBy, driver)); 

arg1 - temporary storage between calls.

Is there any system equivalent function?

+3
source

you can reuse a modified version of the original body expression

 using System; using System.Linq.Expressions; public class Program { public static Expression<Func<T1, TResult>> Bind2nd<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> source, T2 argument) { Expression arg2 = Expression.Constant(argument, typeof (T2)); Expression newBody = new Rewriter(source.Parameters[1], arg2).Visit(source.Body); return Expression.Lambda<Func<T1, TResult>>(newBody, source.Parameters[0]); } public static void Main(string[] args) { Expression<Func<string, string, int>> f = (a, b) => a.Length + b.Length; Console.WriteLine(f); // (a, b) => (a.Length + b.Length) Console.WriteLine(Bind2nd(f, "1")); // a => (a.Length + "1".Length) } #region Nested type: Rewriter private class Rewriter : ExpressionVisitor { private readonly Expression candidate_; private readonly Expression replacement_; public Rewriter(Expression candidate, Expression replacement) { candidate_ = candidate; replacement_ = replacement; } public override Expression Visit(Expression node) { return node == candidate_ ? replacement_ : base.Visit(node); } } #endregion } 
+3
source

All Articles