2009-01-13 59 views
4

當使用Expression.Call時,方法「Any」使用哪些類型和參數?從表達式調用方法

我有一個內部和外部表達式,我想與任何使用。表達式以編程方式構建。

內(這個工程):

ParameterExpression tankParameter = Expression.Parameter(typeof(Tank), "t"); 
Expression tankExpression = Expression.Equal(
    Expression.Property(tankParameter, "Gun"), 
    Expression.Constant("Really Big")); 

Expression<Func<Tank, bool>> tankFunction = 
    Expression.Lambda<Func<Tank, bool>>(tankExpression, tankParameter); 

外(看起來是正確的):

ParameterExpression vehicleParameter = Expression.Parameter(typeof(Vehicle), "v"); 

Expression vehicleExpression = Expression.Lambda(
    Expression.Property(
     vehicleParameter, 
     typeof(Vehicle).GetProperty("Tank")), 
    vehicleParameter); 

這給了我2個表達式:

v => v.Tank 
t => t.Gun == "Really Big"; 

我在找的是:

v => v.Tank.Any(t => t.Gun == "Really Big"); 

我正在嘗試使用Expression.Call方法來使用「Any」。 1.這是正確的做法嗎? 2.以下引發異常, 「No method'任何'類型'System.Linq.Queryable'與提供的參數兼容。」

這裏是我正在呼叫的任何:

Expression any = Expression.Call(
    typeof(Queryable), 
    "Any", 
    new Type[] { tankFunction.Body.Type }, // this should match the delegate... 
    tankFunction); 

如何在任何被調用從vehicleExpression拴tankFunction?

回答

8

我試圖讓string.Contains工作時遇到了類似的問題;我只是使用了GetMethod/MethodInfo的方法;但是 - 這是複雜的,因爲它是一個通用的方法...

這應該是正確的MethodInfo - 但它是很難給出一個完整的(可運行的)回答沒有更多一點的清晰度上TankVehicle

MethodInfo method = typeof(Queryable).GetMethods() 
     .Where(m => m.Name == "Any" 
      && m.GetParameters().Length == 2) 
     .Single().MakeGenericMethod(typeof(Tank)); 

請注意,擴展方法反向工作 - 所以你實際上想用兩個參數(源和謂詞)調用method

喜歡的東西:

MethodInfo method = typeof(Queryable).GetMethods() 
     .Where(m => m.Name == "Any" && m.GetParameters().Length == 2) 
     .Single().MakeGenericMethod(typeof(Tank)); 

    ParameterExpression vehicleParameter = Expression.Parameter(
     typeof(Vehicle), "v"); 
    var vehicleFunc = Expression.Lambda<Func<Vehicle, bool>>(
     Expression.Call(
      method, 
      Expression.Property(
       vehicleParameter, 
       typeof(Vehicle).GetProperty("Tank")), 
      tankFunction), vehicleParameter); 

如果有疑問,可以使用反射鏡(和小提琴有點;-p) - 例如,我寫了一個測試方法,按您的規格:

Expression<Func<Vehicle, bool>> func = v => v.Tank.Any(
    t => t.Gun == "Really Big"); 

並反編譯並玩弄它...