在另一个lambda表达式中使用lambda表达式 [英] Use lambda expression in another lambda expression
问题描述
我需要组合两个lambda表达式,方式是第二个表达式包含第一个。
我搜索了很多但没有找到任何明确的答案...
I need to combine two lambda expressions, in a way that the second expression "contains" the first. I searched a lot but did not find any clear answer...
我想要做的是如下:
第一个表达式expression1作为一个参数传递给一个方法,只用于定义第二个lambda必须在哪个字段或属性上运行。
What i am trying to do is the following : A first expression "expression1" is passed as a parameter to a method, and is simply used to define on which field or property the second lambda must operate.
原来,我试图请执行以下操作:
Schematically, I am trying to do the following :
// simple field selector :
Expression<Func<T, string>> expression1 = obj => obj.field;
// trying to use the field selector in 2nd expression :
Expression<Func<T, bool>> e2 = obj => [[Result of expression1]].Equals("myValue");
换句话说,我想得到:
Expression<Func<T, bool>> e2 = obj => obj.field.Equals("myValue");
我需要这样做,因为它并不总是 Equals )
方法将被调用,但有许多不同的方法。
I need to do it this way because it is not always the Equals()
method that will be called, but many different methods.
我尝试将expression1编译成一个 Func< T ,string>
为了在expression2中调用此Func,但是正如我在LinQ中使用此函数一样,我收到一个异常,因为LinQ不支持Invoke节点类型。
I tried to compile expression1 to a Func<T, string>
in order to invoke this Func in expression2, but as I am using this with LinQ, I get an exception because LinQ does not support Invoke node types.
所以我的问题是:是否有一种方法来组合两个表达式的正文,以及如何?
So my question is : is there a way to just combine the bodies of the two expressions, and how please ?
感谢提前! p>
Thanks by advance !
推荐答案
嗯,这应该是诀窍:
void Main()
{
var execute = Create<TestClass>(
first => first.MyStringField, // field selector
second => second.Equals("1234") // method selector
);
Console.WriteLine(execute(new TestClass("1234"))); // true
Console.WriteLine(execute(new TestClass("4321"))); // false
}
class TestClass
{
public string MyStringField;
public TestClass(string val){
MyStringField = val;
}
}
static Func<TSource, bool> Create<TSource>(
Expression<Func<TSource, string>> fieldSelector,
Expression<Func<string, bool>> methodSelector
)
{
// todo: classical validation of fieldSelector, if necessary.
// todo: classical validation of methodSelector, if necessary.
var compiledFieldSelector = fieldSelector.Compile();
var compiledMethodSelector = methodSelector.Compile();
return T => compiledMethodSelector(compiledFieldSelector(T));
}
注意,由于lambda表达式的本质,您需要验证字段选择器方法选择器,否则可以做一些非常奇怪的事情。
Note, due the nature of lambda expressions, you need to validate the field selector and method selector, otherwise it's possible to do some very weird things.
或者,下一个方法创建不会构成事物的lambda,在这个意义上,这是更好,因为LinqToEntities不应该解释查询问题。
Alternatively, the next approach creates lambda that does not "compose" things, in the sense, this is better since LinqToEntities shouldn't have problems interpreting the query.
static Func<TSource, bool> Create<TSource>(
Expression<Func<TSource, string>> memberSelector,
Expression<Func<string, bool>> methodSelector
)
{
// todo: classical validation of memberSelector, if necessary.
// todo: classical validation of methodSelector, if necessary.
var memberExpression = (MemberExpression)(memberSelector.Body);
var methodCallExpression = (MethodCallExpression)(methodSelector.Body);
// input TSource => ..
var input = Expression.Parameter(typeof(TSource));
var call = Expression.Call(
Expression.MakeMemberAccess(
input,
memberExpression.Member),
methodCallExpression.Method,
methodCallExpression.Arguments);
return Expression.Lambda<Func<TSource, bool>>(call, input)
.Compile();
}
这篇关于在另一个lambda表达式中使用lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!