给定两个泛型类型变量,如何编译 system.linq.expression 树以将它们相乘?如果两种类型之间没有有效的运算符 *,则表达式抛出异常是完全可以接受的。
我选择 System.Linq.Expression 是因为我记得在这里看到它是这样做的,但关于如何做的还不够。
谢谢。
编辑:我选择编译 Linq 表达式以提高速度;这应该尽可能快。
给定两个泛型类型变量,如何编译 system.linq.expression 树以将它们相乘?如果两种类型之间没有有效的运算符 *,则表达式抛出异常是完全可以接受的。
我选择 System.Linq.Expression 是因为我记得在这里看到它是这样做的,但关于如何做的还不够。
谢谢。
编辑:我选择编译 Linq 表达式以提高速度;这应该尽可能快。
您可以通过编写以下代码了解如何执行此操作:
Expression<Func<int, int, int>> multiply =
(left, right) => left * right;
将其编译为程序集并使用 IL 反汇编程序(例如 Reflector)查看 C# 编译器生成的代码。
对于给定的示例,C# 编译器将生成如下内容:
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 });
这正是您指定乘法表达式所需要做的。
当放在泛型方法中时,它可能看起来像这样:
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();
}
尝试这样的事情:
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);
如果 type 没有有效的乘法运算符T
,则该Expression.Multiply
行将引发异常。
我选择了 System.Linq.Expression
只是要清楚:还有另一种简单的方法:
public static T Multiply<T>(T x, T y) {
return ((dynamic)x) * y;
}
并将工作(包括缓存)卸载到框架。另一种选择 - MiscUtil 具有通用的操作员支持,将其包装起来 - 可在此处下载。