Copier ou convertir un arbre d'expression

c# dynamic-language-runtime expression-trees lambda

Question

Comment convertir un ExpressionTree de formulaire

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

à

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

où POCO1 et POCO2 sont des objets C # et possèdent tous les deux la propriété Int32 Age

Réponse acceptée

Eh bien, vous pouvez créer un visiteur d’expression personnalisée qui remplacera les références de paramètre et les expressions d’accès aux membres du correctif.

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

Réponse populaire

Étapes difficiles:


 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.

Le type que vous obtenez ici est une propriété sans setter, comme je l'ai deviné.

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

Donc, vous devez construire une nouvelle expression

Voici le chemin

construit manuellement l'expression linq pour x => x.Child == itemToCompare.Child



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow