Search code examples
c#ironpythonexpression-trees

Getting expression tree from scripting language in c#


I am looking for a way to generate an expression tree from a script in C#. Currently, I am using IronPython, but I am open to switching if it would make it easier to get the expression tree. Also, I realize that I could get this from implementing my own scripting language; however, I would rather use one that is already created if possible.

If a scripting language besides IronPython is recommended, I need it to have: if statements (preferably with and/or), mathematical operations (+,-,*,/,log,%,^), loops, and the ability to add custom functions.

As an example of what I am trying to do, I have included two blocks of code.One calculates the bonus using an expression tree that is created and then compiled:

using System;
using System.Linq.Expressions;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee() { Salary = 100000, BonusPct = .05 };
            Expression<Func<Employee, double>> calcbonusExp = x => x.Salary * x.BonusPct; ;
            var calcBonus = calcbonusExp.Compile();
            Console.WriteLine(calcBonus(employee));
            Console.WriteLine(calcbonusExp.NodeType);
            Console.WriteLine(calcbonusExp.Body);
            Console.WriteLine(calcbonusExp.Body.NodeType);
            foreach (var param in calcbonusExp.Parameters)
            {
                Console.WriteLine(param.Name);
            }
            Console.Read();
        }
}

public class Employee
    {
        public double Salary { get; set; }
        public double BonusPct { get; set; }
    }
}

The other calculates the bonus using IronPython:

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee() { Salary = 100000, BonusPct = .05 };

            ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();

            ScriptSource source = engine.Execute(
                @"def calcBonus(employee):
                      return employee.Salary * employee.BonusPct 
                ", scope);
            var calcAdd = scope.GetVariable("calcBonus");
            var result = calcAdd(employee);
            Console.WriteLine(result);
            Console.Read();
        }
    }

    public class Employee
    {
        public double Salary { get; set; }
        public double BonusPct { get; set; }
    }
}

Is there any way to get the same expression tree out of the block of code using IronPython (or any other scripting language)?


Solution

  • You could use Roslyn to create an Expression object from a script written in C# or VB.

    See e.g. https://www.strathweb.com/2018/01/easy-way-to-create-a-c-lambda-expression-from-a-string-with-roslyn/