2011-01-05 35 views
12

Come convertire un ExpressionTree della formaEspressione Albero Copia o Convertire

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

a

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

dove POCO1 e POCO2 sono oggetti C# ed entrambi hanno proprietà Int32 Età

+0

Cosa stai cercando di fare? Voglio dire, perché vuoi copiarlo così? –

risposta

15

bene, si può fare visitatore espressione personalizzato che andrà a sostituire i riferimenti dei parametri e delle patch espressioni di accesso membri

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

ruvido Passi:

 
 
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 Il tipo che ottieni qui è una proprietà senza setter come ho immaginato.

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

Quindi è necessario costruire una nuova espressione

Qui è il modo

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

0

Idealmente - non lo fai. Creare un'interfaccia che descriva la proprietà Age e creare l'espressione per fare riferimento a che. Se non puoi modificare i tipi POCO, usa un linguaggio come Go, dove le interfacce sono implicite :-).

Problemi correlati