首页 > 解决方案 > Roslyn / CSharpScript - 声明和初始化动态变量以在脚本中使用它们

问题描述

我需要使用许多声明为运行时的变量动态执行 C# 语句。最终用户假设声明变量运行时(仅限某些类型,例如int,string,List<string>,List<int>, bool etc.)并对它们执行操作或评估/执行单行表达式。

为此,我可以看到 Flee 库可以评估表达式并提供动态的机制AddInitialize变量。

例如,可以动态声明变量并使用当前 invuse 变量的值初始化它们,例如:

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 ); 

// 注意变量名称是动态添加到脚本上下文中的,并使用在当前范围内声明的变量进行初始化,并且可以评估如下表达式:

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

或者

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

但是,这仅限于将表达式评估为真/假并仅获取语句的值。这不允许我执行表达式,例如"c = a + b" or "lstStr.Add("PQR")修改对象的值并调用其成员方法。

我可以看到使用 Roslyn / SharpScript 可以执行所需的语句,但是,我没有像 Flee 提供的那样在上下文中动态声明变量并使用当前正在使用的对象初始化它们。

其实我找到了答案,而且很简单。我所需要的只是脚本引擎。为了获取变量,我做了类似于以下代码段中最后一行的操作:

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;

在上面的 Roslyn / CSharpScript 中,如何在脚本上下文中动态声明变量并使用当前使用的对象进行初始化?因为我需要分配已经有大量元素的长列表/集合,并且为它们生成动态代码将是一项挑战。

标签: c#dynamicscriptingroslyncsharpscript

解决方案


您应该使用主机对象,并将其传递给脚本执行/评估:

CSharpScript.RunAsync(code, opt, host);

在主机对象中,您可以定义一个公共属性,如下所示:

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

在 opt 对象中添加引用和导入:

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

(直接导入 Microsoft.CSharp.dll 对我不起作用,我不知道为什么)。然后在您的脚本中,您可以编写如下内容:

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

这些值也可以在脚本之外访问,例如:

host.Vars.minlenght

推荐阅读