Tengo dos expresiones de tipo Expression<Func<T, bool>>
y quiero tomar OR, AND o NOT de estas y obtener una nueva expresión del mismo tipo
Expression<Func<T, bool>> expr1;
Expression<Func<T, bool>> expr2;
...
//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2
c#
linq
lambda
expression
BjartN
fuente
fuente
Respuestas:
Bueno, puedes usar
Expression.AndAlso
/OrElse
etc para combinar expresiones lógicas, pero el problema son los parámetros; ¿Estás trabajando con lo mismoParameterExpression
en expr1 y expr2? Si es así, es más fácil:Esto también funciona bien para negar una sola operación:
De lo contrario, dependiendo del proveedor de LINQ, puede combinarlos con
Invoke
:En algún lugar, tengo un código que reescribe un nodo de reemplazo de árbol de expresión para eliminar la necesidad
Invoke
, pero es bastante largo (y no puedo recordar dónde lo dejé ...)Versión generalizada que elige la ruta más simple:
A partir de .NET 4.0, existe la
ExpressionVisitor
clase que le permite crear expresiones que son seguras para EF.fuente
ExpressionVisitor
) no existía en ese entonces; Tengo un ejemplo relacionado sobre stackoverflow de una fecha similar donde implementa el visitante manualmente: es mucho código.Puede usar Expression.AndAlso / OrElse para combinar expresiones lógicas, pero debe asegurarse de que las Expresiones de parámetros sean las mismas.
Estaba teniendo problemas con EF y PredicateBuilder, así que hice el mío sin recurrir a Invoke, que podría usar así:
Código fuente para mi PredicateBuilder:
Y la clase de utilidad para sustituir los parámetros en una lambda:
fuente
Si su proveedor no es compatible con Invoke y necesita combinar dos expresiones, puede usar un ExpressionVisitor para reemplazar el parámetro en la segunda expresión por el parámetro en la primera expresión.
fuente
No hay nada nuevo aquí, pero casé esta respuesta con esta respuesta y la refacté un poco para que incluso yo entienda lo que está sucediendo:
fuente
Necesitaba lograr los mismos resultados, pero usando algo más genérico (ya que el tipo no se conocía). Gracias a la respuesta de Marc, finalmente descubrí lo que estaba tratando de lograr:
fuente
Sugiero una mejora más para PredicateBuilder y sus
ExpressionVisitor
soluciones. Lo llaméUnifyParametersByName
y puedes encontrarlo en la biblioteca mita de MIT: LinqExprHelper . Permite combinar expresiones arbitrarias lambda. Por lo general, las preguntas se hacen sobre la expresión predicada, pero esta idea también se extiende a las expresiones de proyección.El siguiente código emplea un método
ExprAdres
que crea una expresión parametrizada complicada, usando lambda en línea. Esta expresión complicada se codifica solo una vez y luego se reutiliza, gracias a laLinqExprHelper
mini biblioteca.Y este es el código de construcción de subexpresión:
Lo que intenté lograr fue realizar consultas parametrizadas sin necesidad de copiar y pegar y con la capacidad de usar lambdas en línea, que son muy bonitas. Sin todas estas cosas de expresión auxiliar, me vería obligado a crear una consulta completa de una vez.
fuente
Creo que esto funciona bien, ¿no?
fuente