Is it possible to compile and execute new code at runtime in .NET?

22,048

Solution 1

Yes! Using methods found in the Microsoft.CSharp, System.CodeDom.Compiler, and System.Reflection name spaces. Here is a simple console app that compiles a class ("SomeClass") with one method ("Add42") and then allows you to invoke that method. This is a bare-bones example that I formatted down to prevent scroll bars from appearing in the code display. It is just to demonstrate compiling and using new code at run time.

using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Reflection;

namespace RuntimeCompilationTest {
    class Program
    {
        static void Main(string[] args) {
            string sourceCode = @"
                public class SomeClass {
                    public int Add42 (int parameter) {
                        return parameter += 42;
                    }
                }";
            var compParms = new CompilerParameters{
                GenerateExecutable = false, 
                GenerateInMemory = true
            };
            var csProvider = new CSharpCodeProvider();
            CompilerResults compilerResults = 
                csProvider.CompileAssemblyFromSource(compParms, sourceCode);
            object typeInstance = 
                compilerResults.CompiledAssembly.CreateInstance("SomeClass");
            MethodInfo mi = typeInstance.GetType().GetMethod("Add42");
            int methodOutput = 
                (int)mi.Invoke(typeInstance, new object[] { 1 }); 
            Console.WriteLine(methodOutput);
            Console.ReadLine();
        }
    }
}

Solution 2

You might try this: Calculator.Net

It will evaluate a math expression.

From the posting it will support the following:

MathEvaluator eval = new MathEvaluator();
//basic math
double result = eval.Evaluate("(2 + 1) * (1 + 2)");
//calling a function
result = eval.Evaluate("sqrt(4)");
//evaluate trigonometric 
result = eval.Evaluate("cos(pi * 45 / 180.0)");
//convert inches to feet
result = eval.Evaluate("12 [in->ft]");
//use variable
result = eval.Evaluate("answer * 10");
//add variable
eval.Variables.Add("x", 10);            
result = eval.Evaluate("x * 10");

Download Page And is distributed under the BSD license.

Solution 3

Yes, definitely possible to have the user type C# into a text box, then compile that code and run it from within your app. We do that at my work to allow for custom business logic.

Here is an article (I haven't more than skimmed it) which should get you started:

http://www.c-sharpcorner.com/UploadFile/ChrisBlake/RunTimeCompiler12052005045037AM/RunTimeCompiler.aspx

Solution 4

You can also create a System.Xml.XPath.XPathNavigator from an empty, "dummy" XML stream, and evaluate expressions using the XPath evaluator:

static object Evaluate ( string xp )
{
  return _nav.Evaluate ( xp );
}
static readonly System.Xml.XPath.XPathNavigator _nav
  = new System.Xml.XPath.XPathDocument (
      new StringReader ( "<r/>" ) ).CreateNavigator ( );

If you want to register variables to use within this expression, you can dynamically build XML that you can pass in the Evaluate overload that takes a XPathNodeIterator.

<context>
  <x>2.151</x>
  <y>231.2</y>
</context>

You can then write expressions like "x / 2 * 0.07914" and then x is the value of the node in your XML context. Another good thing is, you will have access to all XPath core functions, which includes mathematics and string manipulation methods, and more stuff.

If you want to take it further, you can even build your own XsltCustomContext(or ill post here on demand) where you can resolve references to extension functions and variables:

object result = Evaluate ( "my:func(234) * $myvar" );

my:func is mapped to a C#/.NET method which takes a double or int as parameter. myvar is registered as a variable within the XSLT context.

Solution 5

I've done this using CSharpCodeProvider by creating the boiler plate class and function stuff as a const string inside my generator class. Then I insert the user code into the boiler plate and compile.

It was fairly straightforward to do, but the danger to this approach is that the user entering the equation could enter just about anything which could be a security issue depending on your application.

If security is at all a concern, I would recommend using Lambda Expression Trees, but if not, using CSharpCodeProvider is a fairly robust option.

Share:
22,048
user422801
Author by

user422801

Updated on May 20, 2020

Comments

  • user422801
    user422801 almost 4 years

    Note: Mathematical expression evaluation is not the focus of this question. I want to compile and execute new code at runtime in .NET. That being said...

    I would like to allow the user to enter any equation, like the following, into a text box:

    x = x / 2 * 0.07914
    x = x^2 / 5
    

    And have that equation applied to incoming data points. The incoming data points are represented by x and each data point is processed by the user-specified equation. I did this years ago, but I didn't like the solution because it required parsing the text of the equation for every calculation:

    float ApplyEquation (string equation, float dataPoint)
    {
        // parse the equation string and figure out how to do the math
        // lots of messy code here...
    }
    

    When you're processing boatloads of data points, this introduces quite a bit of overhead. I would like to be able to translate the equation into a function, on the fly, so that it only has to be parsed once. It would look something like this:

    FunctionPointer foo = ConvertEquationToCode(equation);
    ....
    x = foo(x);  // I could then apply the equation to my incoming data like this
    

    Function ConvertEquationToCode would parse the equation and return a pointer to a function that applies the appropriate math.

    The app would basically be writing new code at run time. Is this possible with .NET?

  • Nick
    Nick over 15 years
    What you want is an expression parser. I did this once by converting the expression from infix to postfix then using a stack based posfix parser. Algorithms for both of these are well defined and exist on the web and in books.
  • cfeduke
    cfeduke over 15 years
    You'll want to look at the CodeDom namespace then, it is possible to compile code at runtime.
  • Philippe Lavoie
    Philippe Lavoie about 13 years
    This library seems to have some bug and do not seems to still be supported.
  • Jonathan Nappee
    Jonathan Nappee about 8 years
    This is very slow for simple arithmetic expressions though.
  • user422801
    user422801 about 8 years
    @JonathanNappee: I was just glad to discover how to do this, I didn't say it was great. I would love to see your performance improvements!
  • Derek
    Derek about 6 years
    @Jonathan Nappee, can you explain your comment some? I want to verify that this method of adding in "Add42" is no slower than having it built-in to the program. To put it another way, your comment was aimed more at "a method that adds 42 is inefficient" rather than "this method of adding code to your program at run time is inefficient," correct?
  • Jonathan Nappee
    Jonathan Nappee about 6 years
    @Derek The very slow part is in the need to compile, create instance and run Invoke. That's probably a few 100s milliseconds overhead. a simple arithmetic parser would be probably an order of magnitude faster.
  • Derek
    Derek about 6 years
    @Jonathan Nappee Thanks for explaining. To make sure I understand how best to use (or not use) this: If you can cache the results of the compile and reuse it multiple times it could potentially offset the overhead cost of said compile. Additionally, complex tasks are far more suited to this method as opposed to simple arithmetic, for simple arithmetic you're probably better off with something like Calculator.Net. Are both of these statements true?
  • Jonathan Nappee
    Jonathan Nappee about 6 years
    @Derek Yes both true.