2010-08-20 98 views
4

我有表達轉換2參數Lambda表達式1個參數Lambda表達式(指定一個參數)

Expression<Func<Car, Driver, bool>> CanBeDrivenBy = 
    (car, driver) => car.Category == 'B' && driver.Age > 18; 

,我想汽車可以通過一些司機

IQueryable<Cars> cars = ...; 
Driver driver = ...; 
cars.Where(CanBeDrivenBy); // Fail, expecting Expression<Func<Car, bool>> 

所以驅動我需要轉換Expression<Func<Car, Driver, bool>>Expression<Func<Car, bool>>(指定驅動程序)

是的我可以使用

cars.Where(c => c.Category == 'B' && driver.Age > 18); 

但我需要動態改變表達式的解決方案。而我需要通過表達式(使用實體框架)

回答

3

這個作品

我寫了這個功能,通過specifing第二個參數從2減少數量的參數爲1。

public static Expression<Func<T1, TResult>> Bind2nd<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> source, T2 argument) 
{ 
     Expression arg2 = Expression.Constant(argument, typeof(T2)); 
     var arg1 = Expression.Parameter(typeof(T1)); 
     return Expression.Lambda<Func<T1, TResult>>(Expression.Invoke(source, arg1, arg2), arg1); 
} 

和使用

IQueryable<Cars> cars = ...; 
Driver driver = ...; 
cars.Where(Bind2nd(CanBeDrivenBy, driver)); 

ARG1是調用之間臨時保管庫。

是否有任何系統等效函數?

+2

你可能想提一提,這就是所謂的鑽營。 – leppie 2010-08-20 11:51:32

+0

哦,哎呀,這也是你的問題:)無論如何,我就是這麼做的。你也許可以更進一步,只使用lambda表達式的主體。 – leppie 2010-08-20 11:52:58

+0

我在C++中學到了這一點,其中函數適配器很常見 – 2010-12-15 21:31:47

3

可以重用源表達身體的修改版本

using System; 
using System.Linq.Expressions; 

public class Program 
{ 
    public static Expression<Func<T1, TResult>> Bind2nd<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> source, T2 argument) 
    { 
     Expression arg2 = Expression.Constant(argument, typeof (T2)); 
     Expression newBody = new Rewriter(source.Parameters[1], arg2).Visit(source.Body); 
     return Expression.Lambda<Func<T1, TResult>>(newBody, source.Parameters[0]); 
    } 

    public static void Main(string[] args) 
    { 
     Expression<Func<string, string, int>> f = (a, b) => a.Length + b.Length; 
     Console.WriteLine(f); // (a, b) => (a.Length + b.Length) 

     Console.WriteLine(Bind2nd(f, "1")); // a => (a.Length + "1".Length) 
    } 

    #region Nested type: Rewriter 

    private class Rewriter : ExpressionVisitor 
    { 
     private readonly Expression candidate_; 
     private readonly Expression replacement_; 

     public Rewriter(Expression candidate, Expression replacement) 
     { 
      candidate_ = candidate; 
      replacement_ = replacement; 
     } 

     public override Expression Visit(Expression node) 
     { 
      return node == candidate_ ? replacement_ : base.Visit(node); 
     } 
    } 

    #endregion 
} 
+0

你可能想提一下你的示例代碼是特定於.NET 4的。 – leppie 2010-08-20 12:08:10

+0

綁定到4.0的唯一部分是ExpressionVisitor。它的實現非常簡單,所以如果需要的話,它可以重構爲較小的框架版本 – desco 2010-08-20 13:25:58

相關問題