sintaxis c# linq

c# - sintaxis - ¿Cómo compongo las expresiones de Linq existentes?



sintaxis linq c# (3)

¿Por qué no solo usa Expression.And ocupa de la BinaryExpression resultante?

Expression<Func<T, bool>> expr1 = t => t.Name == "steve"; Expression<Func<T, bool>> expr2 = t => t.Age == 28; Expression composed = Expression.And(expr1.Body, expr2.Body);

Por supuesto, puedes combinar esto en una lambda para obtener la firma que deseas, pero esto es costoso y solo se debe hacer una vez , no varias veces:

Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>( expr, Expression.Parameter(typeof(T), "t") );

/ EDITAR: Por supuesto, puede combinar lambdas de la siguiente manera, pero esto implica compilaciones redundantes y llamadas a funciones:

Expression<Func<string, bool>> z = t => expr1.Compile()(t) && expr2.Compile()(t);

Maldición, tiempo de inactividad de mantenimiento. Tuve que escribir toda la publicación nuevamente. : - /

/ EDITAR: aku tiene razón, sin embargo. expr2 invocar expr2 separado, de lo contrario, el compilador no encontrará la referencia del parámetro.

Quiero redactar los resultados de dos expresiones de Linq. Ellos existen en la forma

Expression<Func<T, bool>>

Entonces los dos que quiero componer son esencialmente delegados en un parámetro (de tipo T) que ambos devuelven un booleano. El resultado que quisiera compilar sería la evaluación lógica de los booleanos. Probablemente lo implementaría como un método de extensión, así que mi sintaxis sería algo así como:

Expression<Func<User, bool>> expression1 = t => t.Name == "steve"; Expression<Func<User, bool>> expression2 = t => t.Age == 28; Expression<Func<User, bool>> composedExpression = expression1.And(expression2);

Y más adelante en mi código quiero evaluar la expresión compuesta

var user = new User(); bool evaluated = composedExpression.Compile().Invoke(user);

He hurgado con algunas ideas diferentes, pero me temo que es más complejo de lo que esperaba. ¿Cómo se hace esto?



Aquí hay un ejemplo:

var user1 = new User {Name = "steve", Age = 28}; var user2 = new User {Name = "foobar", Age = 28}; Expression<Func<User, bool>> expression1 = t => t.Name == "steve"; Expression<Func<User, bool>> expression2 = t => t.Age == 28; var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); var result = Expression.Lambda<Func<User, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters); Console.WriteLine(result.Compile().Invoke(user1)); // true Console.WriteLine(result.Compile().Invoke(user2)); // false

Puede reutilizar este código a través de métodos de extensión:

class User { public string Name { get; set; } public int Age { get; set; } } public static class PredicateExtensions { public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1,Expression<Func<T, bool>> expression2) { InvocationExpression invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters); } } class Program { static void Main(string[] args) { var user1 = new User {Name = "steve", Age = 28}; var user2 = new User {Name = "foobar", Age = 28}; Expression<Func<User, bool>> expression1 = t => t.Name == "steve"; Expression<Func<User, bool>> expression2 = t => t.Age == 28; var result = expression1.And(expression2); Console.WriteLine(result.Compile().Invoke(user1)); Console.WriteLine(result.Compile().Invoke(user2)); } }