2011-01-05 61 views
12

如何形成的ExpressionTree轉換表達式樹複製或轉換

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

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

其中POCO1和POCO2是C#對象並且都具有的Int32年齡財產

+0

你想做什麼?我的意思是,你爲什麼要像那樣複製它? – 2011-01-05 08:39:40

回答

15

好,你可以自定義表達式遊客將替換參數引用和補丁成員訪問表達式

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

粗糙步驟:

 
 
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你在這裏得到的類型是一個沒有二傳手的財產,因爲我猜測。

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

所以,你必須建立一個新的表達

這裏就是這樣,

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

0

理想情況下 - 你不需要。製作一個描述Age屬性的界面,然後構建表達式來引用。如果您無法修改POCO類型,請使用Go等語言,其中接口是隱含的:-)。