Jim*_*Jim 8 c# lambda expression runtime dynamic
给定一个带有Identification对象的lambda,并返回一个属性:
Expression<Func<Identification, object>> fx = _ => _.Id;
Run Code Online (Sandbox Code Playgroud)
以及将对象转换为标识实例的转换lambda:
ParameterExpression p = Expression.Parameter(typeof(object), "o");
Expression @new = Expression.Lambda(Expression.Convert(p, typeof(Identification)), p);
Run Code Online (Sandbox Code Playgroud)
如何构建一个执行@new(获取标识实例)并将结果传递给的新lambda fx.我需要@new的结果以fx某种方式绑定到第一个参数,我找不到一个例子.
我需要结果是一个Expression,它应该是类型Expression<Func<object, object>>,它应该将入站参数转换为a Identification然后获取Id属性.
首先,请注意,如果您@new正确输入,这会更容易,即:
LambdaExpression @new = ...
Run Code Online (Sandbox Code Playgroud)
因为这样可以轻松访问@new.Body和@new.Parameters; 完成后,
Expression.Invoke在这里很有用:
var combinedParam = Expression.Parameter(typeof(object), "o");
var combined = Expression.Lambda<Func<object, object>>(
Expression.Invoke(fx,
Expression.Invoke(@new, combinedParam)), combinedParam);
Run Code Online (Sandbox Code Playgroud)
虽然对于更清晰的表达式,您也可以使用ExpressionVisitor完全替换内部表达式:
var injected = new SwapVisitor(fx.Parameters[0], @new.Body).Visit(fx.Body);
var combined = Expression.Lambda<Func<object, object>>(injected,@new.Parameters);
Run Code Online (Sandbox Code Playgroud)
有:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
它的作用是:
fx.Body树,用_(替换)参数的所有实例@new.Body(注意这将包含对o参数的引用(又名p)@new,这可以确保我们注入的值将被正确绑定使用Marc Gravell 的回答中的代码,您可以通过辅助函数很好地简化此操作:
public static class ExpressionHelper {
public static Expression<Func<TFrom, TTo>> Chain<TFrom, TMiddle, TTo>(
this Expression<Func<TFrom, TMiddle>> first,
Expression<Func<TMiddle, TTo>> second
) {
return Expression.Lambda<Func<TFrom, TTo>>(
new SwapVisitor(second.Parameters[0], first.Body).Visit(second.Body),
first.Parameters
);
}
private class SwapVisitor : ExpressionVisitor {
private readonly Expression _from;
private readonly Expression _to;
public SwapVisitor(Expression from, Expression to) {
_from = from;
_to = to;
}
public override Expression Visit(Expression node) {
return node == _from ? _to : base.Visit(node);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在看看那多干净!
var valueSelector = new Expression<Func<MyTable, int>>(o => o.Value);
var intSelector = new Expression<Func<int, bool>>(x => x > 5);
var selector = valueSelector.Chain<MyTable, int, bool>(intSelector);
Run Code Online (Sandbox Code Playgroud)
它可以与实体框架和其他需要清理的东西一起使用Expression,而不会尝试在Func其中调用。
| 归档时间: |
|
| 查看次数: |
1765 次 |
| 最近记录: |