我如何编译一个表达式树成一个可调用的方法,C#?
-
19-08-2019 - |
题
我有我已通过使用C#的表达类解析XML创建表达式树。 看到这个问题。
我只有加,减,除,乘,参数,并且还是在我的表达式树。 有没有一种方法来此ExpressionTree转换成可调用的方法? ...或我不得不手动发射IL?
此致
解决方案
下面的两种方法的示例。如果我错过了一些东西,或者你想了解更多信息,只是让我知道。
static void Main()
{
// try to do "x + (3 * x)"
var single = BuildSingle<decimal>();
var composite = BuildComposite<decimal>();
Console.WriteLine("{0} vs {1}", single(13.2M), composite(13.2M));
}
// utility method to get the 3 as the correct type, since there is not always a "int x T"
static Expression ConvertConstant<TSource, TDestination>(TSource value)
{
return Expression.Convert(Expression.Constant(value, typeof(TSource)), typeof(TDestination));
}
// option 1: a single expression tree; this is the most efficient
static Func<T,T> BuildSingle<T>()
{
var param = Expression.Parameter(typeof(T), "x");
Expression body = Expression.Add(param, Expression.Multiply(
ConvertConstant<int, T>(3), param));
var lambda = Expression.Lambda<Func<T, T>>(body, param);
return lambda.Compile();
}
// option 2: nested expression trees:
static Func<T, T> BuildComposite<T>()
{
// step 1: do the multiply:
var paramInner = Expression.Parameter(typeof(T), "inner");
Expression bodyInner = Expression.Multiply(
ConvertConstant<int, T>(3), paramInner);
var lambdaInner = Expression.Lambda(bodyInner, paramInner);
// step 2: do the add, invoking the existing tree
var paramOuter = Expression.Parameter(typeof(T), "outer");
Expression bodyOuter = Expression.Add(paramOuter, Expression.Invoke(lambdaInner, paramOuter));
var lambdaOuter = Expression.Lambda<Func<T, T>>(bodyOuter, paramOuter);
return lambdaOuter.Compile();
}
我个人目的是在该第一种方法;它它既简单,更有效。这可能包括通过整个的嵌套代码堆栈原始参数,但就这样吧。我有一些代码的地方,采取“调用”的方式(复合),并重新写入树作为第一种方法(单) - 但它是相当复杂和漫长。但是,对于实体框架是非常有用的(不支持Expression.Invoke)。
不隶属于 StackOverflow