2012-12-07 106 views
5

有沒有辦法從Expression<Func<T>>構建Expression<Func<T,bool>>如何在表達式<Func<T,bool>>中編寫表達式<Func<T>>

例如,對於類

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

如果Expression<Func<T>>() => new MyClass{Prop2 = 5}然後結果應該是x => x.Prop2 == 5

如果Expression<Func<T>>() => new MyClass{Prop1 = 1, Prop3 = 3}然後結果應該是x => x.Prop1 == 1 && x.Prop3 == 3

換言之是有可能創建FUNC在運行時有任何數量的條件?

+0

您可以使用動態LINQ:http://weblogs.asp.net/scottgu/archive/2008/01 /07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx –

回答

6

像這樣:

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

這很完美。非常感謝你。 – VladK

2

讓我們的代碼不言自語道:

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)); 
     } 
    } 
} 
相關問題