Reputation: 11498
Assume I allow the user to input a arbitrary numerical expression that allows usage of the explicit set of functions and predefined variables.
Interpreting this is pretty straight forward but what if performance is a critical factor?
I need a way to compile (in runtime) a string with a expression into something that can be executed 20K times with different values on the variables.
Upvotes: 2
Views: 831
Reputation: 23562
Linq Samples by Microsoft already contain implementation of extensible Linq parser.
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();
}
You can check out the DbLinq project for sources or this post for more details: Dynamic Linq and Expression Parsing in .NET as a hint of C# compiler extensibility
Upvotes: 2
Reputation: 422122
In C# 4.0, it'll become very easy and straightforward. However, before C# 4.0, I suggest you use Microsoft.JScript
libraries to accomplish it.
This is all you want: http://www.odetocode.com/Articles/80.aspx
Upvotes: 1
Reputation: 1063393
So really you want to parse the string into (eventually) a typed delegate.
One option, then it to parse the string into an Expression
, which you can then compile to a lambda. This is quite complex, but I have some code that will do much of this - but there may be existing parsers that already do the job in full.
As a trivial Expression
example:
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);
The problem is the rest of the parsing code ;-p
I wrote a string
to Expression
parser last week, but it is more code than I'd normally post here... over 300 lines (not including recognition of bespoke external functions, or named arguments (it currently uses anonymous "?" place-holders)).
but if (as you say) interpreting is easy, then perhaps use similar code to write an Expression
that you can compile?
Upvotes: 2