In C# with .NET 3.5, you can use Expression
for this; you can build a parameterised expression and then compile it to a delegate. This is exactly what I did for the maths aspect of Finguistics. I still have the parsing code I used if you want it...
The main trick I used was that to keep the delegate type known, I used an array as the input type - treating different args as arr[0], arr[1], arr[2] etc. This means I could compile to (for example) a Func<decimal[], decimal>
(takes an array of decimal
s, returns a decimal
).
Once you have called Compile()
, this is pertty much as though you had code to do it directly.
(edit)
As a brief example of using Expression
in this way (with a hard-coded function), see below. The parser I have already written currently works as a predicate checker - i.e. to check that "? + (2 * ? - ?) = 22 + ?" - but it wouldn't be hard to change it to return the result instead (and introduce more operations, like sin
/pow
/etc - presumably by mapping them directly to public methods on a helper object (via 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)
{ // just allows "params" usage...
return func(args);
}
}