如何动态地创建一个表达式来; Func键< MyClass的,布尔>>从表达式来谓语; Func键< MyClass的,串>&GT ;? [英] How do I dynamically create an Expression<Func<MyClass, bool>> predicate from Expression<Func<MyClass, string>>?

查看:172
本文介绍了如何动态地创建一个表达式来; Func键< MyClass的,布尔>>从表达式来谓语; Func键< MyClass的,串>&GT ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想追加哪里谓词和我的目标是创建相同的表达式为:

  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键&LT; MyClass的,布尔&GT;&GT;从表达式来谓语; Func键&LT; MyClass的,串&GT;&GT ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆