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?
También puede usar LinqKit, que puede hacer todo este trabajo por usted. Consulte este enlace http://www.albahari.com/nutshell/linqkit.aspx
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));
}
}