2017-10-07 43 views
0

相關:轉換List.Contains到表達式樹

Create a Lambda Expression With 3 conditions

Convert Contains To Expression Tree

在我剛纔的問題我碰到這樣的查詢,我想寫Expression Tree版本如下:

我寫這個代碼:
List<byte?> lst = new List<byte?>{1,2}; 
var param = Expression.Parameter(typeof(T), "o"); 
var body = Expression.AndAlso(
       Expression.Equal(
        Expression.PropertyOrField(param, "Age"), 
        Expression.Constant(20) 
       ), 
       Expression.Call(Expression.PropertyOrField(param, "Status"), 
            "Contains", 
            Type.EmptyTypes, 
            Expression.Constant(lst))); 

var lambda = Expression.Lambda<Func<T, bool>>(body, param); 
return lambda; 

,我得到的錯誤:

"No method 'Contains' exists on type 'System.Nullable`1[System.Byte]'."

請幫我找到問題所在。

感謝

回答

1

的問題是,您可以切換兩個參數Expression.Call,你的代碼試圖創建無意義的表達o.Status.Contains(lst)

你需要切換左右兩個參數:

Expression.Call(Expression.Constant(lst), 
    "Contains", 
    Type.EmptyTypes, 
    Expression.PropertyOrField(param, "Status")) 

這是假設你正在使用LINQ提供程序理解List<T>.Contains()。如果你需要Enumerable.Contains(),那麼看看Ivan Stoev的回答。

2

Convert Contains To Expression Tree的區別在於,我們調用string實例Contains方法,而在這裏我們需要調用一個靜態泛型方法Enumerable.Contains

public static bool Contains<TSource>(
    this IEnumerable<TSource> source, 
    TSource value 
) 

它可以通過使用另一個來實現Expression.Call overload

public static MethodCallExpression Call(
    Type type, 
    string methodName, 
    Type[] typeArguments, 
    params Expression[] arguments 
) 

這樣的:

// Enumerable.Contains<byte?>(lst, a.Status) 
var containsCall = Expression.Call(
    typeof(Enumerable), // type 
    "Contains", // method 
    new Type[] { typeof(byte?) }, // generic type arguments (TSource) 
    Expression.Constant(lst), // arguments (source) 
    Expression.PropertyOrField(param, "Status") // arguments (value) 
);