从另一个表达式创建lambda表达式

时间:2015-03-25 15:56:20

标签: c# lambda expression-trees

我有课:

public class Uid
{ 
    public Guid Id { get; set; }
}

我有一个表达:

void TestMethod<T, TUid>(Expression<Func<T,IUid>> exp1) where TUid : Uid
{
    ....
}

我知道exp1.Body是一个PropertyExpression,它是这样的:(s) => s.UidProperty其中UidProperty是Uid类型的属性。拥有它我应该创建以下表达式:

Expression<Func<T, Guid>> myExp = (s) => s.UidProperty.Id

怎么做?

1 个答案:

答案 0 :(得分:3)

我们可以使用以下Compose方法来获取计算值的表达式,以及使用该输出类型作为其输入类型的另一个表达式来创建表达式,该表达式表示如果结果为第一个表达式传递给第二个表达式:

public static Expression<Func<TFirstParam, TResult>>
    Compose<TFirstParam, TIntermediate, TResult>(
    this Expression<Func<TFirstParam, TIntermediate>> first,
    Expression<Func<TIntermediate, TResult>> second)
{
    var param = Expression.Parameter(typeof(TFirstParam), "param");

    var newFirst = first.Body.Replace(first.Parameters[0], param);
    var newSecond = second.Body.Replace(second.Parameters[0], newFirst);

    return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

这允许我们写:

public Expression<Func<T, Guid>> TestMethod<T, TUid>(
    Expression<Func<T,IUid>> expression) 
    where TUid : Uid
{
    return expression.Compose(uid => uid.Id); 
}