在另一个lambda表达式中使用lambda表达式 [英] Use lambda expression in another lambda expression

查看:138
本文介绍了在另一个lambda表达式中使用lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要组合两个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屋!

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