在C#和.NET 3.5中,您可以使用
Expression
来实现此目的。您可以构建参数化表达式,然后将其编译为委托。这正是我在
Finguistics中用于数学方面的方法。如果您需要,我仍然可以提供我使用的解析代码...
我使用的主要技巧是为了保持委托类型已知,我使用数组作为输入类型 - 将不同的args视为arr[0]、arr
1、arr[2]等。这意味着我可以编译成(例如)一个
Func<decimal[], decimal>
(接受一个
decimal
数组,返回一个
decimal
)。
一旦调用了
Compile()
,就几乎相当于直接编写代码。
(编辑)
以下是使用
Expression
以这种方式(使用硬编码函数)的简短示例。我已经编写的解析器目前作为一个断言检查器工作 - 即检查“? +(2 *?-?)= 22 +?” - 但很容易将其改为返回结果(并引入更多操作,如
sin
/
pow
/等 - 可以通过
Expression.Call
直接将它们映射到帮助对象上的公共方法)。
using System;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
var args = Expression.Parameter(typeof(float[]), "args");
var x = Expression.ArrayIndex(args, Expression.Constant(0));
var y = Expression.ArrayIndex(args, Expression.Constant(1));
var add = Expression.Add(x, y);
var lambda = Expression.Lambda<Func<float[], float>>(add, args);
Func<float[], float> func = lambda.Compile();
Console.WriteLine(func.Call(1, 2));
Console.WriteLine(func.Call(3, 4));
Console.WriteLine(func.Call(5, 6));
}
static T Call<T>(this Func<T[], T> func, params T[] args)
{
return func(args);
}
}