public async Task <bool> ExecuteCode(string code, CancellationToken token = default, IScriptWriter sender = null) { string result = null; object returnedValue = null; bool isError = false; bool isCancelled = false; ScriptExecuted?.Invoke(this, new ScriptRequest { Script = code, Writer = sender }); try { if (!await InitScript(token)) { return(false); } using (await _scriptStateLock.LockAsync(token)) { if (_executionContext != null) { await _executionContext(async() => _scriptState = await _scriptState.ContinueWithAsync(code, cancellationToken: token)); } else { _scriptState = await _scriptState.ContinueWithAsync(code, cancellationToken : token); } returnedValue = _scriptState.ReturnValue; result = _scriptState.ReturnValue?.ToString(); if (_scriptState.ReturnValue != null && _scriptState.ReturnValue.GetType() == typeof(string)) { result = $"\"{result}\""; } } } catch (CompilationErrorException e) { result = e.Message; isError = true; } catch (OperationCanceledException) { result = string.Empty; isCancelled = true; } if (result != null) { var scriptResult = new ScriptResult { Result = result, ReturnedValue = returnedValue, IsError = isError, IsCancelled = isCancelled }; Results.Add(scriptResult); ScriptResultReceived?.Invoke(this, scriptResult); } return(!isError && !isCancelled); }
public async Task <bool> InitScript(CancellationToken token = default) { using (await _scriptStateLock.LockAsync(token)) { if (_scriptState != null) { return(true); } try { var options = ScriptOptions.Default .WithReferences(_references.ToArrayLocked(_lockReferences)) .WithImports(_usings.ToArrayLocked(_lockUsings)); var globals = _globals.ToDictionaryLocked(_lockGlobals); if (globals.Any()) { var createGlobalsScript = CSharpScript.Create(CreateGlobalsType(), options); var image = createGlobalsScript.GetCompilation(); var stream = new MemoryStream(); var result = image.Emit(stream, cancellationToken: token); if (!result.Success) { var scriptResult = new ScriptResult { Result = string.Join("\n", result.Diagnostics.Select(d => d.GetMessage())), IsError = true }; Results.Add(scriptResult); ScriptResultReceived?.Invoke(this, scriptResult); return(false); } var imageArray = ImmutableArray.Create(stream.ToArray()); var portableReference = MetadataReference.CreateFromImage(imageArray); var libAssembly = Assembly.Load(imageArray.ToArray()); var globalsType = libAssembly.GetTypes().FirstOrDefault(t => t.Name == "ScriptGlobals"); var globalsInstance = Activator.CreateInstance(globalsType); foreach (var propInfo in globalsType.GetFields()) { propInfo.SetValue(globalsInstance, globals[propInfo.Name]); } using (var loader = new InteractiveAssemblyLoader()) { loader.RegisterDependency(libAssembly); var script = CSharpScript.Create(string.Empty, options.AddReferences(portableReference), globalsType, loader); _scriptState = await script.RunAsync(globalsInstance, cancellationToken : token); } } else { _scriptState = await CSharpScript.RunAsync(string.Empty, options, cancellationToken : token); } } catch (OperationCanceledException) { _scriptState = null; } } return(_scriptState != null); }