How can I evaluate a C# expression dynamically?

Viewed 115948

I would like to do the equivalent of:

object result = Eval("1 + 3");
string now    = Eval("System.DateTime.Now().ToString()") as string

Following Biri s link, I got this snippet (modified to remove obsolete method ICodeCompiler.CreateCompiler():

private object Eval(string sExpression)
{
    CSharpCodeProvider c = new CSharpCodeProvider();
    CompilerParameters cp = new CompilerParameters();

    cp.ReferencedAssemblies.Add("system.dll");

    cp.CompilerOptions = "/t:library";
    cp.GenerateInMemory = true;

    StringBuilder sb = new StringBuilder("");
    sb.Append("using System;\n");

    sb.Append("namespace CSCodeEvaler{ \n");
    sb.Append("public class CSCodeEvaler{ \n");
    sb.Append("public object EvalCode(){\n");
    sb.Append("return " + sExpression + "; \n");
    sb.Append("} \n");
    sb.Append("} \n");
    sb.Append("}\n");

    CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString());
    if (cr.Errors.Count > 0)
    {
        throw new InvalidExpressionException(
            string.Format("Error ({0}) evaluating: {1}", 
            cr.Errors[0].ErrorText, sExpression));
    }

    System.Reflection.Assembly a = cr.CompiledAssembly;
    object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");

    Type t = o.GetType();
    MethodInfo mi = t.GetMethod("EvalCode");

    object s = mi.Invoke(o, null);
    return s;

}  
9 Answers

If you specifically want to call into code and assemblies in your own project I would advocate using the C# CodeDom CodeProvider.

Here is a list of the most popular approaches that I am aware of for evaluating string expressions dynamically in C#.

Microsoft Solutions

Non-Microsoft solutions (not that there is anything wrong with that)

What are the performance implications of doing this?

We use a system based on something like the above mentioned, where each C# script is compiled to an in-memory assembly and executed in a separate AppDomain. There's no caching system yet, so the scripts are recompiled every time they run. I've done some simple testing and a very simple "Hello World" script compiles in about 0.7 seconds on my machine, including loading the script from disk. 0.7 seconds is fine for a scripting system, but might be too slow for responding to user input, in that case a dedicated parser/compiler like Flee might be better.

using System;
public class Test
{
    static public void DoStuff( Scripting.IJob Job)
    {
        Console.WriteLine( "Heps" );
    }
}

I have just written a similar library (Matheval) in pure C#. It allows evaluating string and number expression like excel fomular.

using System;
using org.matheval;
                    
public class Program
{
    public static void Main()
    {
        Expression expression = new Expression("IF(time>8, (HOUR_SALARY*8) + (HOUR_SALARY*1.25*(time-8)), HOUR_SALARY*time)");
        //bind variable
        expression.Bind("HOUR_SALARY", 10);
        expression.Bind("time", 9);
        //eval
        Decimal salary = expression.Eval<Decimal>();    
        Console.WriteLine(salary);
    }
}

Looks like there is also a way of doing it using RegEx and XPathNavigator to evaluate the expression. I did not have the chance to test it yet but I kind of liked it because it did not require to compile code at runtime or use libraries that could not be available.

http://www.webtips.co.in/c/evaluate-function-in-c-net-as-eval-function-in-javascript.aspx

I'll try it and tell later if it worked. I also intend to try it in Silverlight, but it is too late and I'm almost asleep to do it now.

Related