如何动态创建表达式>来自表达式> 的谓词?
我尝试附加 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 和 的参数命名空间不一样。如果我将表达式选择器之一更改为:
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
很难将编译器生成的表达式树和手工制作的表达式树混合在一起,正是因为这种事情 - 提取参数表达式很棘手。因此,让我们从头开始:
我更改的一个重要方面是传递给
Expression.Parameter
的类型 - 它看起来确实应该是一个Service code> 而不是
string
。我已经尝试过,当我调用 lambda.Compile 并在几个示例 Service 对象上执行它时,它似乎起作用了......
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:
One important aspect I've changed is the type passed to
Expression.Parameter
- it certainly looks like it should be aService
rather than astring
.I've given that a try, and it seemed to work when I called
lambda.Compile
and executed it on a couple of sampleService
objects...您可以为可为空类型创建表达式树,假设您有一个可为空字段 BoardId,您可以像这样动态创建表达式树
您需要确定第一个 Property 类型,无论其是否可为 Nullable
下面的代码为可为 null 和 Non Nullable 类型创建动态树表达式
1 - 此解决方案首先检查 Nullable 值并生成表达式。
这是确定类型是否可为 Null 的方法。我为此目的创建了一个扩展方法
2 - 第二步是检查其字符串的类型,然后为字符串创建一个表达式。
3-第三步是检查值是否不可为空,不是字符串,然后使用 equal 创建一个表达式
You can create an Expression tree for nullable types, suppose you have a nullable field BoardId, you can create expression tree dynamically like this
you need to determine first Property type, whether its Nullable or not
Below code create a Dynamic tree expression for nullable and Non Nullable types
1- This Solution first checks for the Nullable value and generate the expression.
This is How you can determine if the type is Nullable. I have created an extension method for that purpose
2- the second step is to check the type if its string then create an expression for a string.
3- the Third step is to check is value is not nullable not string then create an expression using equal