ExpressionTree 的函数或谓词

发布于 2024-09-13 20:36:39 字数 622 浏览 13 评论 0 原文

可以说我有:

 Func<Customer,bool > a = (c) => c.fullName == "John";

现在我想转换为表达式树,有什么方法可以做到这一点?

我知道我可以从一开始就将它定义为表达式树,但我的情况有所不同,因为我必须首先连接一些 lambda 表达式,然后将其传递给采用表达式树的方法,这样做会导致编译时错误!

示例:

        Func<Customer, bool> a = (c) => c.fullName == "John";
        Func<Customer, bool> b = (c) => c.LastName == "Smith";
        Func<Customer, bool> final = c => a(c) && b(c); 

现在我想将 Final 传递给一个方法,该

ExpressionTree<Func<Customer,bool >>

方法会给出编译时错误,

提前致谢

Lets say i have :

 Func<Customer,bool > a = (c) => c.fullName == "John";

now i want to convert to expressiontree any way to do that ?

i know i can define it from the first place as expressiontree but the situation i have is different because i must concatenate some lambda expressions first then pass it to a method which take expressiontree, doing so result in compile time error!

example:

        Func<Customer, bool> a = (c) => c.fullName == "John";
        Func<Customer, bool> b = (c) => c.LastName == "Smith";
        Func<Customer, bool> final = c => a(c) && b(c); 

now i want to pass final to a method which takes

ExpressionTree<Func<Customer,bool >>

it gives compile time error

thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一个人练习一个人 2024-09-20 20:36:39

你不能那样做。 Func<...> 类型的变量是一个委托,它基本上就像一个指向包含编译代码的内存位置的指针> 为 lambda 表达式。 .NET 中没有将已编译的代码转回表达式树的功能。

根据您尝试执行的操作,也许您可​​以应对不完整的解决方案:创建一个调用委托的表达式树。由于我对您想要将表达式树传递到的方法一无所知,因此我不知道这对您来说是否是一个可行的解决方案。

摘要:如果您想要所有表达式的完整表达式树,则需要确保它们从一开始就是表达式树。一旦将其编译为委托,表达式树就会丢失。

一旦您确定它们是表达式树,您就可以使用如下所示的方式组合它们:

Expression<Func<Customer, bool>> a = c => c.FullName == "John";
Expression<Func<Customer, bool>> b = c => c.LastName == "Smith";

var cp = Expression.Parameter(typeof(Customer), "c");

var ai = Expression.Invoke(a, cp);
var bi = Expression.Invoke(b, cp);

var final = Expression.Lambda<Func<Customer, bool>>(
    Expression.AndAlso(ai, bi), cp);

当然,这使用 AndAlso 运算符 (&&) ;您还可以使用 OrElse 来表示 || 等。

You cannot do that. A variable of type Func<...> is a delegate, which is basically like a pointer to a memory location that contains the compiled code for the lambda expression. There is no functionality in .NET to turn already-compiled code back into an expression tree.

Depending on what you are trying to do, maybe you can contend with an incomplete solution: create an expression tree that calls the delegates. Since I don’t know anything about the method to which you want to pass the expression tree, I have no idea whether this is at all a feasible solution for you.

Summary: If you want the complete expression tree of all the expressions, you need to make sure that they are expression trees right from the start. As soon as you compile it into a delegate, the expression tree is lost.

Once you’ve made sure that they are expression trees, you can combine them using something like the following:

Expression<Func<Customer, bool>> a = c => c.FullName == "John";
Expression<Func<Customer, bool>> b = c => c.LastName == "Smith";

var cp = Expression.Parameter(typeof(Customer), "c");

var ai = Expression.Invoke(a, cp);
var bi = Expression.Invoke(b, cp);

var final = Expression.Lambda<Func<Customer, bool>>(
    Expression.AndAlso(ai, bi), cp);

Of course, this uses the AndAlso operator (&&); you can also use OrElse for || etc.

玉环 2024-09-20 20:36:39

您可以从表达式转到函数,但反之则不行。

你可以这样做:

Expression<Func<Customer, bool>> exprA = (c) => c.fullName == "John";
Func<Customer, bool> funcA = exprA.Compile();

但没有办法走其他路。

You can go from Expression to a Func, but not the other way around.

You can do this:

Expression<Func<Customer, bool>> exprA = (c) => c.fullName == "John";
Func<Customer, bool> funcA = exprA.Compile();

But there's no way to go the other way.

自此以后,行同陌路 2024-09-20 20:36:39

关于您修改后的问题,我认为这会起作用:

Expression<Func<Customer, bool>> a = (c) => c.FullName == "John";
Expression<Func<Customer, bool>> b = (c) => c.LastName == "Smith";

var cp = Expression.Parameter(typeof(Customer), "c");

var ai = Expression.Invoke(a, cp);
var bi = Expression.Invoke(b, cp);

var final = Expression.Lambda<Func<Customer, bool>>(Expression.And(ai, bi), cp);

Regarding your revised question, I think this will work:

Expression<Func<Customer, bool>> a = (c) => c.FullName == "John";
Expression<Func<Customer, bool>> b = (c) => c.LastName == "Smith";

var cp = Expression.Parameter(typeof(Customer), "c");

var ai = Expression.Invoke(a, cp);
var bi = Expression.Invoke(b, cp);

var final = Expression.Lambda<Func<Customer, bool>>(Expression.And(ai, bi), cp);
岁月打碎记忆 2024-09-20 20:36:39

这是我认为适合您的解决方案。我将 Func 转换为 Expression>

它基于 这篇文章 ElegantCode

在这个例子中我使用了一个 Func:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        public static bool Method(Expression<Func<int, bool>> predicate, int value)
        {
            return predicate.Compile()(value);
        }

        static void Main(string[] args)
        {
            Func<int, bool> testPredicate = n => n == 1;
            var output = ConvertFuncToExpression(testPredicate);
            Console.WriteLine(Method(output, 3));
            Console.WriteLine(Method(output, 1));
        }

        private static Expression<TDelegate> CreateExpression<TDelegate>(MethodBase method)
        {
            var delegateArguments = typeof(TDelegate).GetMethod("Invoke").GetParameters().Select((parameter, index) => Expression.Parameter(parameter.ParameterType, "param_" + index)).ToArray();
            if (delegateArguments.Count() != method.GetParameters().Count()) throw new InvalidOperationException("The number of parameters of the requested delegate does not match the number parameters of the specified method.");

            var argumentsTypes = method.GetGenericArguments();
            argumentsTypes = (argumentsTypes.Length > 0) ? argumentsTypes : null;
            var convertedArguments = method.GetParameters().Select((parameter, index) => Expression.Convert(delegateArguments[index], parameter.ParameterType)).ToArray();
            var call = Expression.Call(method.DeclaringType, method.Name, argumentsTypes, convertedArguments);

            var lambda = Expression.Lambda<TDelegate>(call, delegateArguments);
            return lambda;
        }

        private static Expression<Func<TIn1, TOut>> ConvertFuncToExpression<TIn1, TOut>(Func<TIn1, TOut> input)
        {
            MethodInfo method = input.Method;
            return CreateExpression<Func<TIn1, TOut>>(method);
        }
    }
}

Here is a solution that I think will work for you. I converts a Func<TInput, TOutput> to a Expression<Func<TInput, TOutput>>.

It was based in this post from ElegantCode

In this example I used a Func:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        public static bool Method(Expression<Func<int, bool>> predicate, int value)
        {
            return predicate.Compile()(value);
        }

        static void Main(string[] args)
        {
            Func<int, bool> testPredicate = n => n == 1;
            var output = ConvertFuncToExpression(testPredicate);
            Console.WriteLine(Method(output, 3));
            Console.WriteLine(Method(output, 1));
        }

        private static Expression<TDelegate> CreateExpression<TDelegate>(MethodBase method)
        {
            var delegateArguments = typeof(TDelegate).GetMethod("Invoke").GetParameters().Select((parameter, index) => Expression.Parameter(parameter.ParameterType, "param_" + index)).ToArray();
            if (delegateArguments.Count() != method.GetParameters().Count()) throw new InvalidOperationException("The number of parameters of the requested delegate does not match the number parameters of the specified method.");

            var argumentsTypes = method.GetGenericArguments();
            argumentsTypes = (argumentsTypes.Length > 0) ? argumentsTypes : null;
            var convertedArguments = method.GetParameters().Select((parameter, index) => Expression.Convert(delegateArguments[index], parameter.ParameterType)).ToArray();
            var call = Expression.Call(method.DeclaringType, method.Name, argumentsTypes, convertedArguments);

            var lambda = Expression.Lambda<TDelegate>(call, delegateArguments);
            return lambda;
        }

        private static Expression<Func<TIn1, TOut>> ConvertFuncToExpression<TIn1, TOut>(Func<TIn1, TOut> input)
        {
            MethodInfo method = input.Method;
            return CreateExpression<Func<TIn1, TOut>>(method);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文