コード例 #1
0
        private LastCompilationInfo m_LastCompilation = null; // for caching results/compilations

        /// <summary>
        /// Runs the script asynchronously
        /// </summary>
        /// <param name="factory">Factory method to create an IScriptGlobals instance in the current (= the script's) AppDomain</param>
        /// <param name="parameters">Full list of IParameterValues to be passed to the script</param>
        /// <param name="scriptCode">Code of the script</param>
        /// <param name="Options">Options for script execution, compilation or invocation</param>
        /// <param name="submission">Returns an instance of the compiler-generated wrapped script class (e.g. an instance of Submission#0)</param>
        /// <returns>A RemoteTask, so the caller (which could reside in a different AppDomain) can unwrap the results asynchronously</returns>
        public RemoteTask <object> RunAsync(Func <AppDomain, IScriptGlobals> factory, IParameterValue[] parameters, string scriptCode, ScriptingOptions Options)
        {
            string         debug_code_file_path = (Debugger.IsAttached) ? Path.Combine(Path.GetTempPath(), "ExcelScript.DebuggedCode.csx") : null;
            IScriptGlobals globalsInstance      = null;

            try
            {
                scriptCode = RewriteCode(scriptCode, parameters, debug_code_file_path);

                if (debug_code_file_path != null)
                {
                    // todo: might cause problems in multi threaded scenarios / whenever we're running through the .RunAsync() function in parallel.
                    // possibly create varying or even fully random file paths - though though that might need some cleanup logic
                    string line_directive = (debug_code_file_path == null) ? String.Empty : "#line 1 \"" + debug_code_file_path + "\"" + Environment.NewLine;
                    File.WriteAllText(debug_code_file_path, scriptCode);
                    scriptCode = line_directive + scriptCode;
                }

                IMethodSymbol entryPoint;
                var           assembly = GetOrCreateScriptAssembly(parameters.Select(x => x.Parameter).ToArray(), scriptCode, Options, debug_code_file_path, out entryPoint);

                globalsInstance = CreateGlobals(factory, parameters);
                var entryMethod = GetEntryMethod(assembly, entryPoint); // the <factory> method

                var result = RemoteTask.ServerStart <object>(cts => InvokeFactoryAsync(entryMethod, globalsInstance));
                return(result);
            }
            finally
            {
                if (!String.IsNullOrEmpty(debug_code_file_path) && File.Exists(debug_code_file_path))
                {
                    File.Delete(debug_code_file_path);
                }

                IDisposable globalsDisposable = globalsInstance as IDisposable;
                if (globalsDisposable != null)
                {
                    globalsDisposable.Dispose();
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Invokes the factory method (as given by $factoryMethodInfo), and passes the given globalsInstance to this method.
        /// Returns a Task<object> representing the result of the factory method (= the result of the script), and passes the submission object
        /// (i.e. the instance of the underlying script class, eg Submission#0) to the out $submission parameter.
        /// </summary>
        private static async Task <object> InvokeFactoryAsync(MethodInfo factoryMethodInfo, IScriptGlobals globalsInstance)
        {
            // [in]  args[0] -> an instance of the globals variables
            // [out] args[1] -> the constructor of the compiler-generated class (Submission#0) will set this array index to a reference to an instance of the generated class (-> the instance of Submission#0)
            var args = new object[2] {
                globalsInstance, null
            };                                                  // args[0]: globals, args[1]: cancelationtoken

            var task = (Task <object>)factoryMethodInfo.Invoke(null, new object[] { args });

            var taskResult = await task;
            var submission = args[1];

            var result = taskResult;

            return(result);
        }