假设我允许用户输入允许使用显式函数集和预定义变量的任意数值表达式。
解释这一点很简单,但如果性能是一个关键因素呢?
我需要一种方法来(在运行时)将带有表达式的字符串编译成可以在变量上使用不同值执行 20K 次的东西。
假设我允许用户输入允许使用显式函数集和预定义变量的任意数值表达式。
解释这一点很简单,但如果性能是一个关键因素呢?
我需要一种方法来(在运行时)将带有表达式的字符串编译成可以在变量上使用不同值执行 20K 次的东西。
所以你真的想把字符串解析成(最终)一个类型化的委托。
一个选项,然后将字符串解析为Expression
,然后您可以将其编译为 lambda。这是相当复杂的,但我有一些代码可以完成大部分工作——但可能有现有的解析器已经完全完成了这项工作。
作为一个简单的Expression
例子:
var x = Expression.Parameter(typeof(double), "x");
var y = Expression.Parameter(typeof(double), "y");
var body = Expression.Multiply(x, y);
var func = Expression.Lambda<Func<double, double,double>>(body, x, y).Compile();
double z = func(123.45, 678.90);
问题是其余的解析代码;-p
上周我写了一个string
解析器,但它的代码比我通常在这里发布的要多......超过 300 行(不包括识别定制的外部函数或命名参数(它目前使用匿名“?”占位符) Expression
)。
但是如果(如您所说)解释很容易,那么也许使用类似的代码来编写Expression
可以编译的代码?
Microsoft 的 Linq 示例已经包含可扩展 Linq 解析器的实现。
sealed class Order
{
public double SubTotal { get; set; }
public double Shipping { get; set; }
}
static void Main()
{
var calculateTotal = DynamicExpression
.ParseLambda<Order, double>("SubTotal*@0+Shipping", 0.12)
.Compile();
var order = new Order
{
SubTotal = 124.99,
Shipping = 7.99
};
Console.WriteLine(calculateTotal(order));
Console.ReadLine();
}
您可以查看DbLinq 项目的源代码或这篇文章了解更多详细信息:Dynamic Linq and Expression Parsing in .NET as a hint of C# compiler extensibility
在 C# 4.0 中,它会变得非常简单直接。但是,在 C# 4.0 之前,我建议您使用Microsoft.JScript
库来完成它。