2008-12-06 101 views

回答

10

下面是两种方法的示例。如果我错过了某些东西,或者想了解更多信息,请告诉我。

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(); 
} 

就我个人而言,我会瞄准第一种方法;它既简单又高效。这可能涉及将原始参数传递给一堆嵌套代码,但这样做。我有一些代码需要采用“Invoke”方法(复合),并重新编写树作为第一种方法(单个) - 但它非常复杂和漫长。但对Entity Framework非常有用(不支持Expression.Invoke)。

12

你需要创建一个拉姆达 - 即

var lambda = Expression.Lambda<Func<float,int>>(body, param); 
Func<float,int> method = lambda.Compile(); 
int v = method(1.0); // test 

其中 “体” 是你的表达式树(以一个浮点数,返回一个int)涉及​​PARAM。

您可能还会发现thisthis有帮助。

+0

问题是((x + 2)+ y)/ z 当树中有多个不同子表达式的参数部分时,我该怎么做? – 2008-12-06 17:56:05

+0

可能有多个参数(它是ParameterExpression的params数组);对于子表达式,您需要调用内部表达式(Expression.Invoke?) – 2008-12-06 17:58:10

相关问题