問題は、パラメータを変更するために内部を書き直す必要があるため、それらを単に「and」/「or」できないことです。.Body
fromを使用してe1
もパラメータfromを使用すると、機能しません。 ofは、定義されていない完全に無関係なパラメータ インスタンスを参照するe2
ためです。これは、次を使用するとより明白になります。.Body
e1
Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john");
Expression<Func<MyEntity, bool>> e2 = j => j.LName.Contains("smith");
e1
(使用i
とe2
使用の違いに注意してくださいj
)
パラメータを書き換えずにそれらを組み合わせると、無意味になります。
Expression<Func<MyEntity, bool>> combined =
i => i.FName.Contains("john") && j.LName.Contains("smith");
(すごい....どこj
から来たの?)
でも; パラメータの名前に関係なく、問題は同じです。それはまだ別のパラメータです。
また、式は不変であるため、「その場で」交換することはできません。
秘訣は、次のように「ビジター」を使用してノードを書き換えることです。
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);
}
}