2011-01-05 20 views
12

Cómo convertir un ExpressionTree de formaExpresión árbol Copiar o Convertir

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 de C# y ambos tienen la propiedad Int32 Edad

+0

¿Qué estás tratando de hacer? Quiero decir, ¿por qué quieres copiarlo así? –

Respuesta

15

bien, puede hacer que los visitantes expresión personalizada que reemplazará a las referencias de parámetros y parche expresiones de acceso de miembro

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

Rough pasos:

 
 
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. 
 

Th El tipo que obtienes aquí es una propiedad sin setter, como lo imaginé.

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

lo que debe crear una nueva expresión

Esta es la forma

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

0

Idealmente, no es así. Cree una interfaz que describa la propiedad Age y cree la expresión para hacer referencia al que. Si no puede modificar los tipos de POCO, use un idioma como Go, donde las interfaces son implícitas :-).

Cuestiones relacionadas