如何动态地创建一个表达式来; Func键< MyClass的,布尔>>从表达式来谓语; Func键< MyClass的,串>> ;? [英] How do I dynamically create an Expression<Func<MyClass, bool>> predicate from Expression<Func<MyClass, string>>?
问题描述
我想追加哪里谓词和我的目标是创建相同的表达式为:
Services.Where(S = > s.Name ==模块和放大器;&安培; s.Namespace ==命名空间);
我有以下代码:
表达式来; Func键<服务,串>> SEL1 = S = GT; s.Name;
表达式来; Func键<服务,串>> SEL2 = S = GT; s.Namespace;
变种val1中= Expression.Constant(模块);
VAR将val2 = Expression.Constant(命名空间);
表达E1 = Expression.Equal(sel1.Body,VAL1);
表达E2 = Expression.Equal(sel2.Body,将val2);
变种andExp = Expression.AndAlso(E1,E2);
ParameterExpression argParam = Expression.Parameter(typeof运算(字符串),S);
VAR波长= Expression.Lambda<&Func键LT;字符串,布尔>>(andExp,argParam);
这创建以下的输出:
S => ((s.Name ==模块)AndAlso运算(s.Namespace ==命名空间))
然而,这是错误的,因为该参数的名称和命名空间是不一样的。如果我改变表达式选择之一:
表达式来; Func键<服务,串>> SEL2 = SRV => srv.Namespace;
输出将是:
S => ((s.Name ==模块)AndAlso运算(srv.Namespace ==命名空间))
如何建立一个有效的表达与使用 SEL1 和 SEL2
更新的( 2011年2月28日)
我解决它通过创建调用表达式: Expression.Invoke
这样的lambda表情SEL1和SEL2没有必要需要一个MemberExpression:
表达式来; Func键<服务,串>> SEL1 = S = GT; s.Name;
表达式来; Func键<服务,串>> SEL2 = SRV => srv.Namespace;
变种val1中= Expression.Constant(模块);
VAR将val2 = Expression.Constant(命名空间);
表达式来; Func键<服务,布尔>>波长= M =>真正;
VAR modelParameter = lambda.Parameters.First();
// SEL1谓词
{
VAR invokedExpr = Expression.Invoke(SEL1,modelParameter);
VAR binaryExpression = Expression.Equal(invokedExpr,VAL1);
波长= Expression.Lambda<&Func键LT;服务,布尔>>(Expression.AndAlso(binaryExpression,lambda.Body),lambda.Parameters);
}
// SEL2谓词
{
VAR invokedExpr = Expression.Invoke(SEL2,modelParameter);
VAR binaryExpression = Expression.Equal(invokedExpr,将val2);
波长= Expression.Lambda<&Func键LT;服务,布尔>>(Expression.AndAlso(binaryExpression,lambda.Body),lambda.Parameters);
}
这是很难混反编译生成的表达式树和手工制作的人,正是因为这样的事情的 - 提取出来的ParameterExpressions是棘手的。因此,让我们从头开始:
ParameterExpression argParam = Expression.Parameter(typeof运算(服务),S);
表达nameProperty = Expression.Property(argParam,姓名);
表达namespaceProperty = Expression.Property(argParam命名空间);
变种val1中= Expression.Constant(模块);
VAR将val2 = Expression.Constant(命名空间);
表达E1 = Expression.Equal(nameProperty,VAL1);
表达E2 = Expression.Equal(namespaceProperty,将val2);
变种andExp = Expression.AndAlso(E1,E2);
VAR波长= Expression.Lambda<&Func键LT;服务,布尔>>(andExp,argParam);
我改变的一个重要方面是传递给 Expression.Parameter类型
- 这当然看起来的像它应该是一个服务
而非字符串
。
我给一个尝试,它似乎工作,当我叫 lambda.Compile
并执行它的一对夫妇样本服务
对象...
的
I trying to append where predicates and my goal is to create the same expression as:
Services.Where(s => s.Name == "Modules" && s.Namespace == "Namespace");
I have the following code:
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);
This create the following output:
s => ((s.Name == "Modules") AndAlso (s.Namespace == "Namespace"))
However, this is faulty since the parameter for Name and Namespace isn't the same. If I change one of the expression selector to:
Expression<Func<Service,string>> sel2 = srv => srv.Namespace;
The output will be:
s => ((s.Name == "Modules") AndAlso (srv.Namespace == "Namespace"))
How can I create a valid expression with use of sel1 and sel2?
UPDATE (28 feb 2011)
I solved it by creating invoke expressions: Expression.Invoke
so the lambda expressions sel1 and sel2 don't necessary need to be a 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);
}
It's hard to mix compiler-generated expression trees and hand-made ones, precisely because of this sort of thing - extracting out the ParameterExpressions is tricky. So let's start from scratch:
ParameterExpression argParam = Expression.Parameter(typeof(Service), "s");
Expression nameProperty = Expression.Property(argParam, "Name");
Expression namespaceProperty = Expression.Property(argParam, "Namespace");
var val1 = Expression.Constant("Modules");
var val2 = Expression.Constant("Namespace");
Expression e1 = Expression.Equal(nameProperty, val1);
Expression e2 = Expression.Equal(namespaceProperty, val2);
var andExp = Expression.AndAlso(e1, e2);
var lambda = Expression.Lambda<Func<Service, bool>>(andExp, argParam);
One important aspect I've changed is the type passed to Expression.Parameter
- it certainly looks like it should be a Service
rather than a string
.
I've given that a try, and it seemed to work when I called lambda.Compile
and executed it on a couple of sample Service
objects...
这篇关于如何动态地创建一个表达式来; Func键< MyClass的,布尔>>从表达式来谓语; Func键< MyClass的,串>> ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!