2012-12-07 16 views
5

Czy istnieje sposób na zbieranie Expression<Func<T,bool>> z Expression<Func<T>>?Jak wygenerować wyrażenie <Func<T,bool>> z wyrażenia <Func<T>>

Na przykład dla klasy

public class MyClass 
{ 
    public int Prop1{get;set;} 
    public int Prop2{get;set;} 
    public int Prop3{get;set;} 
} 

jeśli Expression<Func<T>> jest () => new MyClass{Prop2 = 5} wtedy wynik powinien być x => x.Prop2 == 5

jeśli Expression<Func<T>> jest () => new MyClass{Prop1 = 1, Prop3 = 3} wtedy wynik powinien być x => x.Prop1 == 1 && x.Prop3 == 3

Innymi słowy jest to możliwe stworzenie func z dowolną liczbą warunków w czasie wykonywania?

+0

Można użyć dynamicznej LINQ: http://weblogs.asp.net/scottgu/archive/2008/01 /07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx –

Odpowiedz

6

Jak to:

static Expression<Func<T,bool>> Munge<T>(Expression<Func<T>> selector) 
{ 
    var memberInit = selector.Body as MemberInitExpression; 
    if (memberInit == null) 
     throw new InvalidOperationException("MemberInitExpression is expected"); 
    var p = Expression.Parameter(typeof(T), "x"); 

    Expression body = null; 
    foreach (MemberAssignment binding in memberInit.Bindings) 
    { 
     var comparer = Expression.Equal(
      Expression.MakeMemberAccess(p, binding.Member), 
      binding.Expression); 
     body = body == null ? comparer : Expression.AndAlso(body, comparer); 
    } 
    if (body == null) body = Expression.Constant(true); 

    return Expression.Lambda<Func<T, bool>>(body, p); 
} 
+0

To jest idealne. Dziękuję Ci bardzo. – VladK

2

Spójrzmy prawdzie w kodzie mówią za siebie:

class Program 
{ 
    static Expression<Func<T, bool>> Transform<T>(Expression<Func<T>> expression) 
    { 
     var initExpression = expression.Body as MemberInitExpression; 
     if (initExpression == null) 
     { 
      throw new ArgumentException(); 
     } 

     Expression bodyExpression = Expression.Constant(true); 
     IEnumerable<MemberBinding> bindings = initExpression.Bindings; 
     ParameterExpression param = Expression.Parameter(typeof(T)); 

     foreach (var memberBinding in bindings) 
     { 
      var memberAssigment = memberBinding as MemberAssignment; 
      if (memberAssigment == null) 
      { 
       throw new ArgumentException(); 
      } 

      var member = memberAssigment.Member; 
      var value = memberAssigment.Expression; 

      bodyExpression = Expression.AndAlso(
       bodyExpression, 
       Expression.Equal(
        Expression.MakeMemberAccess(param, member), 
        value 
       ) 
      ); 
     } 

     return Expression.Lambda<Func<T, bool>>(bodyExpression, param); 
    } 

    static void Main(string[] args) 
    { 
     Expression<Func<MyClass>> exp =() => new MyClass { Prop1 = 1, Prop3 = 3 }; 

     var result = Transform(exp); 
     var lambda = result.Compile(); 

     var array = new[] 
     { 
      new MyClass { Prop1 = 1, Prop3 = 3 }, 
      new MyClass { Prop1 = 1, Prop2 = 2, Prop3 = 3 }, 
      new MyClass { Prop1 = 1, Prop3 = 1 }, 
      new MyClass { Prop1 = 3, Prop3 = 3 }, 
      new MyClass { Prop1 = 3, Prop3 = 1 }, 
      new MyClass() 
     }; 

     foreach (var o in array) 
     { 
      Console.WriteLine(lambda(o)); 
     } 
    } 
} 
Powiązane problemy