Roslyn / CSharpScript - Declare and Initialize Dynamic Variables to use them in script

1.3k views Asked by At

I am having a requirement to execute C# statement dynamically with a number of variables declared runtime. End-user suppose to declare variables runtime ( of certain types only like int,string,List<string>,List<int>, bool etc. ) and perform operations on them or evaluate / execute single-line expressions.

For this purpose, I can see Flee library works to evaluate expressions and provides a mechanism to Add and Initialize variables dynamically.

For e.g. one can declare variables dynamically and initialize them with values of currently invuse variables like:

int var1 = 2;
int var2 = 25;
List<string> _lstStr = new List<string>();
_lstStr.Add("ABC");
_lstStr.Add("DEF");

ExpressionContext context1 = new ExpressionContext();
context1.Variables.Add("var1", var1);
context1.Variables.Add("var2", var2);
context1.Variables.Add("_lstStr", _lstStr ); 

// Note Variable Names are Dynamically added to script context and initialized with variables declared in current scope and one can evaluate expressions like :

var expression = new Expressions.DynamicExpression(" a > b " , ExpressionLanguage.Csharp);

OR

var expression = new Expressions.DynamicExpression("lstStr[0]=="abc"" , ExpressionLanguage.Csharp);

However, this is limited to evaluate the expression to true/false and just getting the value of the statement. This does not allow me to execute expressions like "c = a + b" or "lstStr.Add("PQR") to modify an object's value and invoke its member method.

I can see with Roslyn / SharpScript one can execute required statements, however, I am not getting way like Flee provides to declare variables dynamically in context and initialize them with currently in-use objects.

Actually I found the answer and it was quite simple. All I needed was the Scripting engine. To get variables I did something like the last line in the following snippet:

var script = CSharpScript.Create("");
script = script.ContinueWith("int a = 10;"); 
script = script.ContinueWith("int b = 20;");

script = script.ContinueWith("List<string> _myList = "); // how to assign current List<string> object here ?

var vars = script.RunAsync().Result.Variables;

In the above Roslyn / CSharpScript how to declare variables dynamically in script context and initialize with currently used objects? As I need to assign long Lists/collections already having a huge number of elements and it would be challenging to generate on-fly code for them.

1

There are 1 answers

0
andreat On

you should use host object, and pass it in the script execution/evaluation:

CSharpScript.RunAsync(code, opt, host);

in host object you can define a public property like this:

public dynamic Vars = new System.Dynamic.ExpandoObject();

add reference and imports in opt object:

ScriptOptions opt = ScriptOptions.Default;
opt = opt.AddReferences(typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Assembly);

(import directly Microsoft.CSharp.dll doesn't work for me, I dont konw why). Then in your script you can write something like:

Vars.minlenght = 5;    
Vars.maxlenght = 10;

And these values are accesible also outside the script, for example:

host.Vars.minlenght