2017-05-20 49 views
0

考慮一類可被用作多種其他類的成員撰寫調用與Customer相關聯。如果我想在內存中的檢查,我不喜歡這樣寫道:與表達<Func<T,bool>>相同的方式,函數功能<T,bool>

static Func<T,bool> Check<T>(Func<T,Customer> conv, string first, string last) { 
    return obj => conv(obj).FirstName == first && conv(obj).LastName == last; 
} 

我可以用我的檢查在內存中的序列如下:

var matchingOrders = orders 
    .Where(Check<Order>(x => x.Customer, "Foo", "Bar")) 
    .ToList(); 
var matchingProfiles = profiles 
    .Where(Check<Profile>(x => x.Customer, "Foo", "Bar")) 
    .ToList(); 

現在我想要做同樣的事情與Expression<Func<T,bool>>

static Expression<Func<T,bool>> Check<T>(Expression<Func<T,Customer>> conv, string first, string last) 

不幸的是,同樣的伎倆行不通:

return obj => conv(obj).FirstName == first && conv(obj).LastName == last; 

,並使用它像這樣:

var matchingOrders = dbContext.Orders 
    .Where(Check<Order>(x => x.Customer, "Foo", "Bar")) 
    .ToList(); 
var matchingProfiles = dbContext.Profiles 
    .Where(Check<Profile>(x => x.Customer, "Foo", "Bar")) 
    .ToList(); 

這會觸發一個錯誤:

CS0119: Expression denotes a variable', where a method group' was expected

我可以撰寫表情,我代表組成的一樣嗎?

+0

建議的重複是死錯誤的:它由兩個相同的表情,而我撰寫鏈中的不同類型的表達式。投票重新開放。 – dasblinkenlight

回答

0

不幸的是,C#目前沒有提供從Expression<Func<...>>對象中編寫表達式的方法。你必須使用表達式目錄樹,這是相當長的時間:

static Expression<Func<T,bool>> CheckExpr<T>(Expression<Func<T,Customer>> conv, string first, string last) { 
    var arg = Expression.Parameter(typeof(T)); 
    var get = Expression.Invoke(conv, arg); 
    return Expression.Lambda<Func<T,bool>>(
     Expression.MakeBinary(
      ExpressionType.AndAlso 
     , Expression.MakeBinary(
       ExpressionType.Equal 
      , Expression.Property(get, nameof(Customer.FirstName)) 
      , Expression.Constant(first) 
      ) 
     , Expression.MakeBinary(
       ExpressionType.Equal 
      , Expression.Property(get, nameof(Customer.LastName)) 
      , Expression.Constant(last) 
      ) 
     ) 
    , arg 
    ); 
} 
+0

事實上,你可以帶兩個類似謂詞的表達式樹,然後使用樹遍歷來創建一個&& - 組合式或||-組合式謂詞式副本,因爲IIRC不能只重用已經存在的原始副本綁定在該樹中(參數表達式會阻止它在樹葉)。如果部件採用相同的參數,它會更容易。我已經看到它已經實現,有人創建了一個通用表達式樹Visitor,其中之一樣本,有一個例子,結合OR運算符的where子句.. argh,我只是找到正確的話來谷歌它現在:/ – quetzalcoatl

+0

哈!找到了!當然,這是舊的,2008年,但這樣的東西不生鏽! [請參閱此文章](https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/)。它從[另一篇文章](http://blogs.msdn.com/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspx)使用ExpressionVisitor來構建'Compose ','.And()'和'.Or()'擴展方法 - 尤其是,請檢查第一篇文章中的最後一個例子,看看如何看到它的可重用性和便利性。 (順便說一句,現在是9年以後,現在還沒有在BCL ..) – quetzalcoatl

+0

嗯..對不起,我可能今天用完了所有的空閒時間:/也許你可以找點時間收集所有的代碼來自這些文章的一些位?作爲同樣問題的另一個答案..如果這個實用程序最終會從互聯網上消失,那將是一種恥辱 – quetzalcoatl

相關問題