Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }