Copia o conversión del árbol de expresiones

c# dynamic-language-runtime expression-trees lambda

Pregunta

Cómo convertir un ExpressionTree de forma

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

a

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

donde POCO1 y POCO2 son objetos C # y ambos tienen la propiedad Int32 Age

Respuesta aceptada

así, puede hacer que el visitante de expresiones personalizadas reemplace las referencias de parámetros y las expresiones de acceso de miembros de parches

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);

Respuesta popular

Pasos ásperos:


 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.

El tipo que se obtiene aquí es una propiedad sin establecedor, como lo supuse.

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

Así que debes construir una nueva expresión.

Aquí está el camino

construir manualmente la expresión linq para x => x.Child == itemToCompare.Child



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué