相關:
在我上一個問題的下面,我遇到了這個查詢,我想編寫Expression Tree
版本:
List<byte?> lst = new List<byte?>{1,2};
from a in myTbl
where a.Age = 20 && lst.Contains(a.Status)
select a
我寫這段代碼:
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;
我收到錯誤:
“類型'System.Nullable`1 [System.Byte]'上沒有方法'包含'。”
請幫我找到問題所在。
謝謝
問題是你已經將兩個參數切換到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的答案。
轉換包含到表達式樹的區別在於我們在那裡調用了一個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)
);