表达式树复制或转换

时间:2011-01-05 07:49:16

标签: c# lambda expression-trees dynamic-language-runtime

如何转换表单的ExpressionTree

Expression<Func<POCO1, bool>> exp = p => p.Age > 50;

Expression<Func<POCO2, bool>> exp2 = p => p.Age > 50;

其中POCO1和POCO2是C#对象,并且都具有Int32 Age属性

3 个答案:

答案 0 :(得分:17)

好吧,您可以创建将替换参数引用和修补程序成员访问表达式的自定义表达式访问者

class Converter<TTo>
{
    class ConversionVisitor : ExpressionVisitor
    {
        private readonly ParameterExpression newParameter;
        private readonly ParameterExpression oldParameter;

        public ConversionVisitor(ParameterExpression newParameter, ParameterExpression oldParameter)
        {
            this.newParameter = newParameter;
            this.oldParameter = oldParameter;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return newParameter; // replace all old param references with new ones
        }

        protected override Expression VisitMember(MemberExpression node)
        {
            if (node.Expression != oldParameter) // if instance is not old parameter - do nothing
                return base.VisitMember(node);

            var newObj = Visit(node.Expression);
            var newMember = newParameter.Type.GetMember(node.Member.Name).First();
            return Expression.MakeMemberAccess(newObj, newMember);
        }
    }

    public static Expression<Func<TTo, TR>> Convert<TFrom, TR>(
        Expression<Func<TFrom, TR>> e
        )
    {
        var oldParameter = e.Parameters[0];
        var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name);
        var converter = new ConversionVisitor(newParameter, oldParameter);
        var newBody = converter.Visit(e.Body);
        return Expression.Lambda<Func<TTo, TR>>(newBody, newParameter);
    }
}

class A
{
    public int Value { get; set; }
}

class B
{
    public int Value { get; set; }
}

Expression<Func<A, int>> f = x => x.Value;
var f2 = Converter<B>.Convert(f);

答案 1 :(得分:1)

粗略步骤:


 Get the expression Cast it to BinaryExpression
 Get the left operand Cast it to MemberExpression
 Get the Underlying Type that the property belong to 
 Change it to your new type if you can.

我猜到的这种类型是没有二传手的属性。

Expression<Func<MainWindow, bool >> exp1 = o => this.ActualHeight>50;
var type = ((MemberExpression)((BinaryExpression)exp1.Body).Left).Expression.Type;

所以你必须建立一个新的表达

这是方式

manually build linq expression for x => x.Child == itemToCompare.Child

答案 2 :(得分:0)

理想情况下 - 你没有。创建一个描述Age属性的接口,并构建表达式以引用 。如果您无法修改POCO类型,请使用Go这样的语言,其中接口是隐式的: - )。