How can I evaluate C# code dynamically?
Asked Answered
K

16

114

I can do an eval("something()"); to execute the code dynamically in JavaScript. Is there a way for me to do the same thing in C#?

An example of what I am trying to do is: I have an integer variable (say i) and I have multiple properties by the names: "Property1", "Property2", "Property3", etc. Now, I want to perform some operations on the " Propertyi " property depending on the value of i.

This is really simple with Javascript. Is there any way to do this with C#?

Krahling answered 7/8, 2008 at 12:26 Comment(4)
Take a look at Mono's CSharp interactive shell. It has eval-like functions.Danube
c# call ironpython's eval. I tried it in c# 4.0. no experience with c# 2.0Isocyanide
@Peter Long, where can I find documentation on IronPython's eval ?Bride
@AdhipGupta I know that this Q&A is pretty dated, but I have just released a video playlist that sounds a whole lot like the description given in Davide Icardi's answer. It is dramatically different, and probably worth checking out.Adrian
B
51

DISCLAIMER: This answer was written back in 2008. The landscape has changed drastically since then.

Look at the other answers on this page, especially the one detailing Microsoft.CodeAnalysis.CSharp.Scripting.

Rest of answer will be left as it was originally posted but is no longer accurate.


Unfortunately, C# isn't a dynamic language like that.

What you can do, however, is to create a C# source code file, full with class and everything, and run it through the CodeDom provider for C# and compile it into an assembly, and then execute it.

This forum post on MSDN contains an answer with some example code down the page somewhat:
create a anonymous method from a string?

I would hardly say this is a very good solution, but it is possible anyway.

What kind of code are you going to expect in that string? If it is a minor subset of valid code, for instance just math expressions, it might be that other alternatives exists.


Edit: Well, that teaches me to read the questions thoroughly first. Yes, reflection would be able to give you some help here.

If you split the string by the ; first, to get individual properties, you can use the following code to get a PropertyInfo object for a particular property for a class, and then use that object to manipulate a particular object.

String propName = "Text";
PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);

Link: PropertyInfo.SetValue Method

Brilliance answered 7/8, 2008 at 12:31 Comment(5)
what if GetProperty has to be a function with x,y params ?, means Text(1,2) ?Piper
@Piper Then you will need to use GetMethod(methodName) instead, parse the parameter values, and call the method using reflection.Brilliance
typeof(ObjectType) is analog to someObject.GetType()Desantis
This answer is no longer correct. It's possible to evaluate and execute scripts using the CSharpScript class in the Microsoft.CodeAnalysis.Scripting package. People are closing similar questions using this as a duplicate, which causes confusionSollie
I agree this answer is not correct anymore. The accepted answer should ideally be moved to one of the others here. Though I disagree somewhat with the closing suggestion, as you're not linking to duplicate answers, instead to duplicate questions and sometimes it is not the accepted answer that is the answer to the one being closed as a duplicate.Brilliance
P
67

Using the Roslyn scripting API. More samples in the Rolsyn wiki.

// add NuGet package 'Microsoft.CodeAnalysis.Scripting'
using Microsoft.CodeAnalysis.CSharp.Scripting;

await CSharpScript.EvaluateAsync("System.Math.Pow(2, 4)") // returns 16

You can also run any piece of code:

var script = await CSharpScript.RunAsync(@"
                class MyClass
                { 
                    public void Print() => System.Console.WriteLine(1);
                }")

And reference the code that was generated in previous runs:

await script.ContinueWithAsync("new MyClass().Print();");
Paction answered 23/6, 2016 at 6:33 Comment(0)
B
51

DISCLAIMER: This answer was written back in 2008. The landscape has changed drastically since then.

Look at the other answers on this page, especially the one detailing Microsoft.CodeAnalysis.CSharp.Scripting.

Rest of answer will be left as it was originally posted but is no longer accurate.


Unfortunately, C# isn't a dynamic language like that.

What you can do, however, is to create a C# source code file, full with class and everything, and run it through the CodeDom provider for C# and compile it into an assembly, and then execute it.

This forum post on MSDN contains an answer with some example code down the page somewhat:
create a anonymous method from a string?

I would hardly say this is a very good solution, but it is possible anyway.

What kind of code are you going to expect in that string? If it is a minor subset of valid code, for instance just math expressions, it might be that other alternatives exists.


Edit: Well, that teaches me to read the questions thoroughly first. Yes, reflection would be able to give you some help here.

If you split the string by the ; first, to get individual properties, you can use the following code to get a PropertyInfo object for a particular property for a class, and then use that object to manipulate a particular object.

String propName = "Text";
PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);

Link: PropertyInfo.SetValue Method

Brilliance answered 7/8, 2008 at 12:31 Comment(5)
what if GetProperty has to be a function with x,y params ?, means Text(1,2) ?Piper
@Piper Then you will need to use GetMethod(methodName) instead, parse the parameter values, and call the method using reflection.Brilliance
typeof(ObjectType) is analog to someObject.GetType()Desantis
This answer is no longer correct. It's possible to evaluate and execute scripts using the CSharpScript class in the Microsoft.CodeAnalysis.Scripting package. People are closing similar questions using this as a duplicate, which causes confusionSollie
I agree this answer is not correct anymore. The accepted answer should ideally be moved to one of the others here. Though I disagree somewhat with the closing suggestion, as you're not linking to duplicate answers, instead to duplicate questions and sometimes it is not the accepted answer that is the answer to the one being closed as a duplicate.Brilliance
U
14

Not really. You can use reflection to achieve what you want, but it won't be nearly as simple as in Javascript. For example, if you wanted to set the private field of an object to something, you could use this function:

protected static void SetField(object o, string fieldName, object value)
{
   FieldInfo field = o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
   field.SetValue(o, value);
}
Upbringing answered 7/8, 2008 at 12:31 Comment(0)
E
13

This is an eval function under c#. I used it to convert anonymous functions (Lambda Expressions) from a string. Source: http://www.codeproject.com/KB/cs/evalcscode.aspx

public static object Eval(string sCSCode) {

  CSharpCodeProvider c = new CSharpCodeProvider();
  ICodeCompiler icc = c.CreateCompiler();
  CompilerParameters cp = new CompilerParameters();

  cp.ReferencedAssemblies.Add("system.dll");
  cp.ReferencedAssemblies.Add("system.xml.dll");
  cp.ReferencedAssemblies.Add("system.data.dll");
  cp.ReferencedAssemblies.Add("system.windows.forms.dll");
  cp.ReferencedAssemblies.Add("system.drawing.dll");

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

  StringBuilder sb = new StringBuilder("");
  sb.Append("using System;\n" );
  sb.Append("using System.Xml;\n");
  sb.Append("using System.Data;\n");
  sb.Append("using System.Data.SqlClient;\n");
  sb.Append("using System.Windows.Forms;\n");
  sb.Append("using System.Drawing;\n");

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

  CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
  if( cr.Errors.Count > 0 ){
      MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText, 
         "Error evaluating cs code", MessageBoxButtons.OK, 
         MessageBoxIcon.Error );
      return null;
  }

  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;

}
Eloyelreath answered 23/6, 2011 at 16:25 Comment(2)
@sehe Whoops, I corrected the typo (Lambada => Lambda). I didn't knew that the song is called Lambada so this one was unintentional. ;)Eloyelreath
I could not understand why this answer get less vote. It's very useful.Abomb
T
12

I have written an open source project, Dynamic Expresso, that can convert text expression written using a C# syntax into delegates (or expression tree). Expressions are parsed and transformed into Expression Trees without using compilation or reflection.

You can write something like:

var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");

or

var interpreter = new Interpreter()
                      .SetVariable("service", new ServiceExample());

string expression = "x > 4 ? service.SomeMethod() : service.AnotherMethod()";

Lambda parsedExpression = interpreter.Parse(expression, 
                          new Parameter("x", typeof(int)));

parsedExpression.Invoke(5);

My work is based on Scott Gu article http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

Tivoli answered 3/2, 2013 at 9:29 Comment(0)
R
7

All of that would definitely work. Personally, for that particular problem, I would probably take a little different approach. Maybe something like this:

class MyClass {
  public Point point1, point2, point3;

  private Point[] points;

  public MyClass() {
    //...
    this.points = new Point[] {point1, point2, point3};
  }

  public void DoSomethingWith(int i) {
    Point target = this.points[i+1];
    // do stuff to target
  }
}

When using patterns like this, you have to be careful that your data is stored by reference and not by value. In other words, don't do this with primitives. You have to use their big bloated class counterparts.

I realized that's not exactly the question, but the question has been pretty well answered and I thought maybe an alternative approach might help.

Rowdyish answered 7/8, 2008 at 12:47 Comment(0)
M
5

I don't now if you absolutely want to execute C# statements, but you can already execute Javascript statements in C# 2.0. The open-source library Jint is able to do it. It's a Javascript interpreter for .NET. Pass a Javascript program and it will run inside your application. You can even pass C# object as arguments and do automation on it.

Also if you just want to evaluate expression on your properties, give a try to NCalc.

Mistaken answered 14/10, 2009 at 8:6 Comment(0)
C
4

You can use reflection to get the property and invoke it. Something like this:

object result = theObject.GetType().GetProperty("Property" + i).GetValue(theObject, null);

That is, assuming the object that has the property is called "theObject" :)

Circuitry answered 7/8, 2008 at 12:29 Comment(0)
F
1

You also could implement a Webbrowser, then load a html-file wich contains javascript.

Then u go for the document.InvokeScript Method on this browser. The return Value of the eval function can be catched and converted into everything you need.

I did this in several Projects and it works perfectly.

Hope it helps

Forgotten answered 1/10, 2010 at 17:3 Comment(0)
L
1

Uses reflection to parse and evaluate a data-binding expression against an object at run time.

DataBinder.Eval Method

Longobard answered 5/11, 2011 at 14:40 Comment(0)
C
1

I have written a package, SharpByte.Dynamic, to simplify the task of compiling and executing code dynamically. The code can be invoked on any context object using extension methods as detailed further here.

For example,

someObject.Evaluate<int>("6 / {{{0}}}", 3))

returns 3;

someObject.Evaluate("this.ToString()"))

returns the context object's string representation;

someObject.Execute(@
"Console.WriteLine(""Hello, world!"");
Console.WriteLine(""This demonstrates running a simple script"");
");

runs those statements as a script, etc.

Executables can be gotten easily using a factory method, as seen in the example here--all you need is the source code and list of any expected named parameters (tokens are embedded using triple-bracket notation, such as {{{0}}}, to avoid collisions with string.Format() as well as Handlebars-like syntaxes):

IExecutable executable = ExecutableFactory.Default.GetExecutable(executableType, sourceCode, parameterNames, addedNamespaces);

Each executable object (script or expression) is thread-safe, can be stored and reused, supports logging from within a script, stores timing information and last exception if encountered, etc. There is also a Copy() method compiled on each to allow creating cheap copies, i.e. using an executable object compiled from a script or expression as a template for creating others.

Overhead of executing an already-compiled script or statement is relatively low, at well under a microsecond on modest hardware, and already-compiled scripts and expressions are cached for reuse.

Caul answered 14/8, 2017 at 11:28 Comment(1)
Is this still available? Maybe in a NuGet Package with another name..?Disrespectful
R
0

You could do it with a prototype function:

void something(int i, string P1) {
    something(i, P1, String.Empty);
}

void something(int i, string P1, string P2) {
    something(i, P1, P2, String.Empty);
}

void something(int i, string P1, string P2, string P3) {
    something(i, P1, P2, P3, String.Empty);
}

and so on...

Retrad answered 7/8, 2008 at 12:30 Comment(0)
L
0

I was trying to get a value of a structure (class) member by it's name. The structure was not dynamic. All answers didn't work until I finally got it:

public static object GetPropertyValue(object instance, string memberName)
{
    return instance.GetType().GetField(memberName).GetValue(instance);
}

This method will return the value of the member by it's name. It works on regular structure (class).

Lychnis answered 2/5, 2018 at 13:56 Comment(0)
M
0

You might check the Heleonix.Reflection library. It provides methods to get/set/invoke members dynamically, including nested members, or if a member is clearly defined, you can create a getter/setter (lambda compiled into a delegate) which is faster than reflection:

var success = Reflector.Set(instance, null, $"Property{i}", value);

Or if number of properties is not endless, you can generate setters and chache them (setters are faster since they are compiled delegates):

var setter = Reflector.CreateSetter<object, object>($"Property{i}", typeof(type which contains "Property"+i));
setter(instance, value);

Setters can be of type Action<object, object> but instances can be different at runtime, so you can create lists of setters.

Modulation answered 13/7, 2018 at 10:4 Comment(0)
U
-1

Unfortunately, C# doesn't have any native facilities for doing exactly what you are asking.

However, my C# eval program does allow for evaluating C# code. It provides for evaluating C# code at runtime and supports many C# statements. In fact, this code is usable within any .NET project, however, it is limited to using C# syntax. Have a look at my website, http://csharp-eval.com, for additional details.

Ultraconservative answered 10/6, 2011 at 2:24 Comment(1)
Have a look at Roslyn Scripting APIPhi
D
-10

the correct answer is you need to cache all the result to keep the mem0ry usage low.

an example would look like this

TypeOf(Evaluate)
{
"1+1":2;
"1+2":3;
"1+3":5;
....
"2-5":-3;
"0+0":1
} 

and add it to a List

List<string> results = new List<string>();
for() results.Add(result);

save the id and use it in the code

hope this helps

Dimarco answered 26/8, 2011 at 12:37 Comment(1)
somebody confused evaluation with lookup. If you know all possible programs (I think that is at least NP-Hard)... and you have a supermachine to precompile all possible results... and there are no sideeffects/external inputs... Yeah, this idea theoretically works. The code is one big syntax error, thoughMccune

© 2022 - 2024 — McMap. All rights reserved.