我正在使用基于roslyn-ctp的脚本规则引擎,它将处理IEnumerable<T>
并将结果返回为IEnumerable<T>
。为了避免创建ScriptEngine
,一次又一次地配置和解析,我想重用ScriptEngine
的一个实例。
以下是一个简短的示例(full sample at gist.github.com):
var engine = new ScriptEngine();
new[]
{
typeof (Math).Assembly,
this.GetType().Assembly
}.ToList().ForEach(assembly => engine.AddReference(assembly));
new[]
{
"System", "System.Math",
typeof(Model.ProcessingModel).Namespace
} .ToList().ForEach(@namespace => engine.ImportNamespace(@namespace));
IEnumerable<Model.ProcessingModel> models = new[]
{
new Model.ProcessingModel { InputA = 10M, InputB = 5M, Factor = 0.050M },
new Model.ProcessingModel { InputA = 20M, InputB = 2M, Factor = 0.020M },
new Model.ProcessingModel { InputA = 12M, InputB = 3M, Factor = 0.075M }
};
// no dynamic allowed
// anonymous class are duplicated in assembly
var script =
@"
Result = InputA + InputB * Factor;
Delta = Math.Abs((Result ?? 0M) - InputA);
Description = ""Some description"";
var result = new { Σ = Result, Δ = Delta, λ = Description };
result
";
// Here is ArgumentException `Duplicate type name within an assembly`
IEnumerable<dynamic> results =
models.Select(model => engine.CreateSession(model).Execute(script));
以下是几个问题:
dynamic
关键字Duplicate type name within an assembly
System.Reflection.Emit
当脚本包含匿名类型时,有没有办法创建ScriptEngine
并多次重复使用?
答案 0 :(得分:2)
你正在罗斯林遇到一个错误。
我建议不要在循环中编译脚本。由于代码不会更改,因此仅更新脚本正在使用的数据会更有效。这种方法也避免了这个错误。
var model = new Model();
var session = engine.CreateSession(model);
var submission = session.CompileSubmission<dynamic>(script);
foreach (Model data in models)
{
model.InputA = data.InputA;
model.InputB = data.InputB;
model.Factor = data.Factor;
dynamic result = submission.Execute();
Console.WriteLine("{0} {1} {2}", result.Σ, result.Δ, result.λ);
}