Копирование или преобразование дерева выражений - PullRequest
12 голосов
/ 05 января 2011

Как преобразовать 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 ]

17 голосов
/ 05 января 2011

хорошо, вы можете сделать пользовательское выражение посетителем, которое заменит ссылки на параметры и исправит выражения доступа к члену

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 голос
/ 05 января 2011

Грубые шаги:

<s>
 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.
</s>

Тип, который вы здесь получаете, это свойство без установщика, как я и догадывался.

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

Так что вы должны построить новыйвыражение

Вот способ

вручную построить выражение linq для x => x.Child == itemToCompare.Child

0 голосов
/ 06 января 2011

В идеале - нет. Создайте интерфейс, который описывает свойство Age, и постройте выражение для ссылки на , что . Если вы не можете изменить типы POCO, используйте такой язык, как Go, где неявные интерфейсы: -).

...