2015-08-14 3 views
1

У меня есть такое выражение, как: Expression<Func<TheObject, int, bool>> myExpression = (myObj, theType) => { myObj.Prop > theType };Rebuild Expression

мне нужно динамически перестраивать myExpression к новому выражению типа Expression<Func<TheObject, bool>> и заменить параметр «theType» из первого выражения с конкретным значением 123, как:

Expression<Func<TheObject, bool>> myNewExpression = myObj => { myObj.Prop > 123 }; 

Как я могу это сделать? Br Филипп

+0

Что вы имеете в виду под «динамически»? Во время выполнения? – netaholic

+0

У вас нет 'Expression' там ... Удалите '{' и '}', ** тогда ** вы получите 'Expression' (см. Http://goo.gl/Sl86ie) – xanatos

+0

У меня есть метод, который принимает первое выражение как параметр и целочисленное значение в качестве делегата, это должно возвращать новое выражение, например: 'Expression > RebuildExpression (Expression > myExpression, Func theInt) ' – Philip

ответ

1

С помощью простого выражения Заменитель это довольно легко:

Это один я написал для себя ... поддерживает простые заменяет и несколько заменяет.

using System; 
using System.Collections.Generic; 
using System.Linq.Expressions; 

// A simple expression visitor to replace some nodes of an expression 
// with some other nodes. Can be used with anything, not only with 
// ParameterExpression 
public class SimpleExpressionReplacer : ExpressionVisitor 
{ 
    public readonly Dictionary<Expression, Expression> Replaces; 

    public SimpleExpressionReplacer(Expression from, Expression to) 
    { 
     Replaces = new Dictionary<Expression, Expression> { { from, to } }; 
    } 

    public SimpleExpressionReplacer(Dictionary<Expression, Expression> replaces) 
    { 
     // Note that we should really clone from and to... But we will 
     // ignore this! 
     Replaces = replaces; 
    } 

    public SimpleExpressionReplacer(IEnumerable<Expression> from, IEnumerable<Expression> to) 
    { 
     Replaces = new Dictionary<Expression, Expression>(); 

     using (var enu1 = from.GetEnumerator()) 
     using (var enu2 = to.GetEnumerator()) 
     { 
      while (true) 
      { 
       bool res1 = enu1.MoveNext(); 
       bool res2 = enu2.MoveNext(); 

       if (!res1 || !res2) 
       { 
        if (!res1 && !res2) 
        { 
         break; 
        } 

        if (!res1) 
        { 
         throw new ArgumentException("from shorter"); 
        } 

        throw new ArgumentException("to shorter"); 
       } 

       Replaces.Add(enu1.Current, enu2.Current); 
      } 
     } 
    } 

    public override Expression Visit(Expression node) 
    { 
     Expression to; 

     if (node != null && Replaces.TryGetValue(node, out to)) 
     { 
      return base.Visit(to); 
     } 

     return base.Visit(node); 
    } 
} 

Ваш TheObject

public class TheObject 
{ 
    public int Prop { get; set; } 
} 

Тогда вам нужно только заменить 2-й параметр в теле выражения и перестроить Expression<>

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     Expression<Func<TheObject, int, bool>> myExpression = (myObj, theType) => myObj.Prop > theType; 

     int value = 123; 

     var body = myExpression.Body; 

     var body2 = new SimpleExpressionReplacer(myExpression.Parameters[1], Expression.Constant(value)).Visit(body); 

     Expression<Func<TheObject, bool>> myExpression2 = Expression.Lambda<Func<TheObject, bool>>(body2, myExpression.Parameters[0]); 
    } 
} 
+0

Отлично, спасибо! Прекрасно работает! – Philip

+0

'SimpleExpressionReplacer' - хорошо написанный класс! –