Expression Tree Copy or Convert

后端 未结 3 1085
温柔的废话
温柔的废话 2020-12-08 22:55

How to convert a ExpressionTree of form

Expression> exp = p => p.Age > 50;

to

Express         


        
相关标签:
3条回答
  • 2020-12-08 23:11

    Rough Steps:

    
     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.
    
    

    The type you get here is a property without setter as I guessed.

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

    So you must build a new expression

    Here is the way

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

    0 讨论(0)
  • 2020-12-08 23:20

    Ideally - you don't. Make an interface that describes the Age property, and build the expression to refer to that. If you can't modify the POCO types, use a language like Go, where interfaces are implicit :-).

    0 讨论(0)
  • 2020-12-08 23:26

    well, you can make custom expression visitor that will replace parameter references and patch member access expressions

    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);
    
    0 讨论(0)
提交回复
热议问题