简体   繁体   中英

Given two generic type variables, how do I compile a system.linq.expression tree to multiply them?

Given two generic type variables, how do I compile a system.linq.expression tree to multiply them? It's perfectly acceptable if the expression throws an exception if the two types do not have a valid operator * between them.

I chose System.Linq.Expression because I recall seeing it done that way on here, but not enough about how.

Thanks.

Edit: I chose compiling a Linq expression for speed; this should be as fast as reasonably possible.

You can find out how to do this by writing the following code:

Expression<Func<int, int, int>> multiply = 
    (left, right) => left * right;

Compiling it down to an assembly and use a IL deassembler (such as Reflector) to look at the code the C# compiler produced.

With the given example, the C# compiler will generate something like this:

var left = Expression.Parameter(typeof(int), "left");
var right = Expression.Parameter(typeof(int), "right");

var multiply = Expression.Lambda<Func<int, int, int>>(
    Expression.Multiply(left, right),
    new ParameterExpression[] { left, right });

And this is exactly what you need to do to specify a multiply expression.

When placed in a generic method, it might look something like this:

public static Func<T, T, T> BuildMultiplier<T>()
{
    var left = Expression.Parameter(typeof(T), "left");
    var right = Expression.Parameter(typeof(T), "right");

    var multiply = Expression.Lambda<Func<T, T, T>>(
        Expression.Multiply(left, right),
        new ParameterExpression[] { left, right });

    return multiply.Compile();
}

Try something like this:

var left = Expression.Parameter(typeof(T), "left");
var right = Expression.Parameter(typeof(T), "right");
var body = Expression.Multiply(left, right);
return Expression.Lambda<Func<T, T, TResult>>(body, left, right);

If there is no valid multiplication operator for type T , the Expression.Multiply line will throw an exception.

I chose System.Linq.Expression

Just to be clear: there's another easy way:

public static T Multiply<T>(T x, T y) {
    return ((dynamic)x) * y;
}

and offload the work (including cache) to the framework. Another option - MiscUtil has generic operator support that wraps this up - downloadable here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM