Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C#
Article

Runtime C# Expression Evaluator

Rate me:
Please Sign up or sign in to vote.
4.83/5 (71 votes)
20 Apr 2002Ms-PL1 min read 272.4K   4K   97   36
A C# class (and library if needed) to do runtime evaluations of C# expressions

Introduction

This is a simple class library (or just .cs file if you wish) to allow for runtime compilation and evaluation of C# code blocks. There are both static methods of the Evaluator class that allow for simple use (but at a performance penalty) or you can use the object directly to create multiple evaluations:

C#
Console.WriteLine("Test0: {0}", Evaluator.EvaluateToInteger("(30 + 4) * 2"));
Console.WriteLine("Test1: {0}", Evaluator.EvaluateToString("\"Hello \" + \"There\""));
Console.WriteLine("Test2: {0}", Evaluator.EvaluateToBool("30 == 40"));
Console.WriteLine("Test3: {0}", Evaluator.EvaluateToObject("new DataSet()"));

EvaluatorItem[] items = {
                          new EvaluatorItem(typeof(int), "(30 + 4) * 2", "GetNumber"),
                          new EvaluatorItem(typeof(string), "\"Hello \" + \"There\"", 
                                                            "GetString"),
                          new EvaluatorItem(typeof(bool), "30 == 40", "GetBool"),
                          new EvaluatorItem(typeof(object), "new DataSet()", "GetDataSet")
                        };

Evaluator eval = new Evaluator(items);
Console.WriteLine("TestStatic0: {0}", eval.EvaluateInt("GetNumber"));
Console.WriteLine("TestStatic1: {0}", eval.EvaluateString("GetString"));
Console.WriteLine("TestStatic2: {0}", eval.EvaluateBool("GetBool"));
Console.WriteLine("TestStatic3: {0}", eval.Evaluate("GetDataSet"));

How does it work? I am using the CodeDOM to create a simple assembly with a single class in it. I simply transform each of the EvaluatorItems into a method of the class. When you call EvaluateInt() or Evaluate(), I use reflection to get a MethodInfo object and call the method.

The source code comes packaged in a Class Library with a Test program that you can use to get examples of use:

To compile the expressions, I am creating a new CSharpCodeProvider and setting Compiler attributes (like adding references, telling it to generate it in memory, etc.). Then I am building a dummy class that I can append my methods on. Lastly I compile it (check for errors) and save the object to use to call with the MethodInfo structure:

C#
ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler());
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.ReferencedAssemblies.Add("system.data.dll");
cp.ReferencedAssemblies.Add("system.xml.dll");
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;

StringBuilder code = new StringBuilder();
code.Append("using System; \n");
code.Append("using System.Data; \n");
code.Append("using System.Data.SqlClient; \n");
code.Append("using System.Data.OleDb; \n");
code.Append("using System.Xml; \n");
code.Append("namespace ADOGuy { \n");
code.Append("  public class _Evaluator { \n");
foreach(EvaluatorItem item in items)
{
  code.AppendFormat("    public {0} {1}() ", 
                    item.ReturnType.Name, 
                    item.Name);
  code.Append("{ ");
  code.AppendFormat("      return ({0}); ", item.Expression);
  code.Append("}\n");
}
code.Append("} }");

CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
if (cr.Errors.HasErrors)
{
  StringBuilder error = new StringBuilder();
  error.Append("Error Compiling Expression: ");
  foreach (CompilerError err in cr.Errors)
  {
    error.AppendFormat("{0}\n", err.ErrorText);
  }
  throw new Exception("Error Compiling Expression: " + error.ToString());
}
Assembly a = cr.CompiledAssembly;
_Compiled = a.CreateInstance("ADOGuy._Evaluator");

When I call the _Compiled object, I use a MethodInfo object to Invoke the call and return the result to the user:

C#
public object Evaluate(string name)
{
  MethodInfo mi = _Compiled.GetType().GetMethod(name);
  return mi.Invoke(_Compiled, null);
}

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Renju Vinod9-May-13 2:14
professionalRenju Vinod9-May-13 2:14 
QuestionString Expression evaluation Pin
specialdreamsin13-Jun-12 23:27
specialdreamsin13-Jun-12 23:27 
QuestionUsage of this code Pin
Gonzalo Méndez Díaz24-Apr-12 17:14
Gonzalo Méndez Díaz24-Apr-12 17:14 
QuestionWhat about Double type ? Pin
Kronborn28-Mar-12 2:16
Kronborn28-Mar-12 2:16 
GeneralMy vote of 5 Pin
MohammadAmiry3-Nov-11 1:30
MohammadAmiry3-Nov-11 1:30 
GeneralMy vote of 5 Pin
Nagy Vilmos2-May-11 0:18
professionalNagy Vilmos2-May-11 0:18 
GeneralMy vote of 5 Pin
Yvan Rodrigues28-Mar-11 10:47
professionalYvan Rodrigues28-Mar-11 10:47 
GeneralMy vote of 5 Pin
joyichantg21-Mar-11 20:30
joyichantg21-Mar-11 20:30 
GeneralMy vote of 5 Pin
kaikg31-Aug-10 4:51
kaikg31-Aug-10 4:51 
GeneralGood job! Pin
kaikg31-Aug-10 4:51
kaikg31-Aug-10 4:51 
GeneralMy vote of 5 Pin
Igor Gresovnik16-Aug-10 11:58
Igor Gresovnik16-Aug-10 11:58 
GeneralThanks Pin
jigi_chavan13-Oct-09 1:02
jigi_chavan13-Oct-09 1:02 
Generalpls help Pin
Xandip30-Sep-09 4:50
Xandip30-Sep-09 4:50 
Generalgreat tool! Pin
abomb2229-May-09 5:10
abomb2229-May-09 5:10 
RantDownload link is not working Pin
parslej27-Mar-09 4:58
parslej27-Mar-09 4:58 
GeneralBoolean expression evaluator Pin
jackietrillo17-Feb-09 17:22
jackietrillo17-Feb-09 17:22 
AnswerRe: Boolean expression evaluator Pin
Member 820-Feb-09 10:37
Member 820-Feb-09 10:37 
QuestionLicence ? Pin
asalmi16-Sep-08 6:12
asalmi16-Sep-08 6:12 
AnswerRe: Licence ? Pin
Gonzalo Méndez Díaz11-Feb-10 6:19
Gonzalo Méndez Díaz11-Feb-10 6:19 
Questiondoes it evaluate the expression ? Pin
Paresh Gheewala7-Aug-08 21:21
Paresh Gheewala7-Aug-08 21:21 
GeneralGarbage Collection Pin
TGKelley14-Aug-07 15:25
TGKelley14-Aug-07 15:25 
Questioncan a web project use "ReferencedAssemblies.Add("customer.dll")" Pin
wlbkeats7-Dec-06 23:34
wlbkeats7-Dec-06 23:34 
GeneralEval custom classes Pin
Pluisjeh15-Mar-06 0:41
Pluisjeh15-Mar-06 0:41 
GeneralEval Objects Pin
ZiggY816-Mar-06 3:52
ZiggY816-Mar-06 3:52 
GeneralIt's Great! Pin
James Yang20-Feb-06 3:16
James Yang20-Feb-06 3:16 
It's Just what i have been looking for.

warning
'System.CodeDom.Compiler.CodeDomProvider.CreateCompiler()' is obsolete: 'Callers should not use the ICodeCompiler interface and should instead use the methods directly on the CodeDomProvider class. Those inheriting from CodeDomProvider must still implement this interface, and should exclude this warning or also obsolete this method.'

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.