Using IronPython for Dynamic Expressions.

We recently had this question posted to our forums over at LVS:

Dear Forum Experts:

I am looking for very specialized solution:

I have various Items which I store into a table in a Relational DB.
I would like to do a custom calculation, specific for each item at it's instance. Because the calculation is specific for the item, and items are soo many I wold like to store the calculation formula into a relational DB. The problem is to convert the string of formula into a real programming command and to actually perform the calculation. I do not want to use Excel or additional software in order to gain calculation speed e.g.

ItemID = 5001, ItemSize = "a - b"
ItemID = 5002, ItemSize = "a - 2*b"
ItemID = 5003, ItemSize = "a + b"

So, ItemSize is actually the formula expression that would calculate various instances of a and b variables ... I have tryed this:

int a = 10;
int b = 5;

string formula = "a + b" // This comes from ItemSIze of DB,SQL, etc.

int Result = a + b; // This is a second line for test only - hard coded...

int CalcResult = int.Parse(formula); //I wish this was working ...

MessageBox.Show(Result.ToString()); // This works ...
MessageBox.Show(CalcResult.ToString()); // Never got that far.

The result will be stored in different DB with the instances of a and b.
Could you please post any information on how should I approach this problem.

Thanks a lot.

Several options immediately came to mind: code up a simple expression interpreter, evaluate the expression with dynamic SQL (yuck), use lightweight code gen. Then I remembered this little thing I saw at last years PDC called IronPython. Solving this problem with IronPython was "like butta".

using System; using System.Collections.Generic; using System.Text; using IronPython.Hosting; namespace PythonDemo { class Program { delegate int MyExpressionDelegate(int a, int b); static void Main(string[] args) { PythonEngine pe = new PythonEngine(); MyExpressionDelegate expression = pe.CreateLambda<MyExpressionDelegate>("a + b"); int a = 10; int b = 5; int c = expression(a,b); Console.WriteLine(c); } } }

That's all there was to it! The API for the PythonEngine was very intuitive. I could immediately see where and how I could integrate this with any number of applications that I've worked on in the past. Tip of the hat to the IronPython guys!

Now I haven't tested this against a simple interpreter but I would imagine as long as you are smart and keep a cache of the expressions and don't re-parse them every time that it would perform just as well as any interpreted solution if not better. Just follow the make it work, make it work right and make it work fast model and you'll be ok.

I wonder if this would also be possible by referenceing the PowerShell runtime. I'll have to take a look at that next and see how it compares.

P.S. Microsoft, if you're listening, please include IronPython in the Orcas/NETFX3.5 release! :) I'd love to see IDE support for python scripts and such.

No Comments