El problema es que se puede no sólo "y"/"o" ellos, porque es necesario volver a escribir las partes internas para cambiar los parámetros; si usa .Body
desde e1
, pero el parámetro desde e2
, no funcionará, porque el .Body
de e1
hace referencia a una instancia de parámetro completamente no relacionada que no está definida. Esto es más obvia si utiliza:
Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = j => j.LName.Contains("smith");
(tenga en cuenta la diferencia entre e1
usando i
y e2
usando j
)
Si los combinamos sin reescribir el parámetro, que se pueden conseguir los esperpentos:
Expression<Func<MyEntity, bool>> combined =
i => i.FName.Contains("john") && j.LName.Contains("smith");
(woah .... ¿de dónde vienen de j
?)
SIN EMBARGO; el problema es idéntico independientemente del nombre del parámetro: sigue siendo un parámetro diferente.
Y como la expresión es inmutable, no puede simplemente cambiarla "en su lugar".
El truco es usar un "visitante" para reescribir los nodos, así:
using System;
using System.Linq.Expressions;
class SwapVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public SwapVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
static class Program
{
static void Main()
{
Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = i => i.LName.Contains("smith");
// rewrite e1, using the parameter from e2; "&&"
var lambda1 = Expression.Lambda<Func<MyEntity, bool>>(Expression.AndAlso(
new SwapVisitor(e1.Parameters[0], e2.Parameters[0]).Visit(e1.Body),
e2.Body), e2.Parameters);
// rewrite e1, using the parameter from e2; "||"
var lambda2 = Expression.Lambda<Func<MyEntity, bool>>(Expression.OrElse(
new SwapVisitor(e1.Parameters[0], e2.Parameters[0]).Visit(e1.Body),
e2.Body), e2.Parameters);
}
}
Combinar * cómo * - "y también"? –
sí, y también. Quiero combinar estos en tiempo de ejecución. – PickleRick