让我们说:
Func<Customer,bool > a = (c) => c.fullName == "John";
现在我想以任何方式转换为expressiontree吗?
我知道我可以从第一个地方定义它作为expressiontree但是我的情况不同,因为我必须首先连接一些lambda表达式然后将它传递给一个采用expressiontree的方法,这样做会导致编译时错误!
示例:
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 >>
它给出了编译时错误
提前致谢
答案 0 :(得分:5)
你做不到。类型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
用于||
等。
答案 1 :(得分:2)
你可以从Expression转到Func,但不是相反。
你可以这样做:
Expression<Func<Customer, bool>> exprA = (c) => c.fullName == "John";
Func<Customer, bool> funcA = exprA.Compile();
但是没有办法走另一条路。
答案 2 :(得分:2)
关于你修改过的问题,我认为这样可行:
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);
答案 3 :(得分:1)
这是我认为适合您的解决方案。我将Func<TInput, TOutput>
转换为Expression<Func<TInput, TOutput>>
。
它位于ElegantCode的this post
在这个例子中,我使用了一个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);
}
}
}