首先,请注意,如果你打上@new
,就会更容易。 适当 i.e:
LambdaExpression @new = ...
since that provides easy access to @new.Body
and @new.Parameters
; that done,
Expression.Invoke
can be useful here:
var combinedParam = Expression.Parameter(typeof(object), "o");
var combined = Expression.Lambda<Func<object, object>>(
Expression.Invoke(fx,
Expression.Invoke(@new, combinedParam)), combinedParam);
尽管为了更清洁的表述,你还可以使用<条码>ExpressionVisitor,以完全取代内部表述:
var injected = new SwapVisitor(fx.Parameters[0], @new.Body).Visit(fx.Body);
var combined = Expression.Lambda<Func<object, object>>(injected,@new.Parameters);
注
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);
}
}
这是:
- inspect the
fx.Body
tree, replacing all instances of _
(the parameter) with the @new.Body
(note that this will contain references to the o
parameter (aka p
)
- we then build a new lambda from the replaced expression, re-using the same parameters from
@new
, which ensures that the values we injected will be bound correctly