我试图添加 where 谓词,并且我的目标是创建与以下表达式相同的表达式:
Services.Where(s => s.Name == "Modules" && s.Namespace == "Namespace");
我有以下代码:
Expression<Func<Service,string>> sel1 = s => s.Name;
Expression<Func<Service,string>> sel2 = s => s.Namespace;
var val1 = Expression.Constant("Modules");
var val2 = Expression.Constant("Namespace");
Expression e1 = Expression.Equal(sel1.Body, val1);
Expression e2 = Expression.Equal(sel2.Body, val2);
var andExp = Expression.AndAlso(e1, e2);
ParameterExpression argParam = Expression.Parameter(typeof(string), "s");
var lambda = Expression.Lambda<Func<string, bool>>(andExp, argParam);
这会生成以下输出:
s => ((s.Name == "Modules") AndAlso (s.Namespace == "Namespace"))
然而,这种方法是错误的,因为 Name 和 Namespace 的参数并不相同。如果我将其中一个表达式选择器更改为:Expression<Func<Service,string>> sel2 = srv => srv.Namespace;
输出结果将为:
s => ((s.Name == "Modules") AndAlso (srv.Namespace == "Namespace"))
如何使用 sel1 和 sel2 创建有效的表达式?更新 (2011 年 2 月 28 日):
我通过创建调用表达式
Expression.Invoke
来解决这个问题,因此 lambda 表达式 sel1 和 sel2 不一定需要是 MemberExpression。Expression<Func<Service,string>> sel1 = s => s.Name;
Expression<Func<Service,string>> sel2 = srv => srv.Namespace;
var val1 = Expression.Constant("Modules");
var val2 = Expression.Constant("Namespace");
Expression<Func<Service, bool>> lambda = m => true;
var modelParameter = lambda.Parameters.First();
// sel1 predicate
{
var invokedExpr = Expression.Invoke(sel1, modelParameter);
var binaryExpression = Expression.Equal(invokedExpr, val1);
lambda = Expression.Lambda<Func<Service, bool>>(Expression.AndAlso(binaryExpression, lambda.Body), lambda.Parameters);
}
// sel2 predicate
{
var invokedExpr = Expression.Invoke(sel2, modelParameter);
var binaryExpression = Expression.Equal(invokedExpr, val2);
lambda = Expression.Lambda<Func<Service, bool>>(Expression.AndAlso(binaryExpression, lambda.Body), lambda.Parameters);
}