Beispiel #1
0
        private static object InternalSerialize(string HandleName, bool Compress = false, string OutputFilePath = null)
        {
            HandleName = HandleNames.GetNameFrom(HandleName);
            IStoredObject storedObj;

            if (!m_ObjectStore.GetByName(HandleName, out storedObj))
            {
                throw new Exception($"No object named {HandleName} found");
            }

            bool WriteToFile = !String.IsNullOrWhiteSpace(OutputFilePath);

            var obj = new SerializationWrapper {
                ContainedObject = storedObj
            };
            var result = XmlSerialize <SerializationWrapper>(obj);

            if (Compress)
            {
                var       compressed = Zip(result);
                XDocument doc        = new XDocument(new XElement("CompressedData", new XAttribute("Algorithm", "gzip"), Convert.ToBase64String(compressed)));

                if (WriteToFile)
                {
                    OutputFilePath = Environment.ExpandEnvironmentVariables(OutputFilePath);

                    using (var fileWriter = new FileStream(OutputFilePath, FileMode.Create))
                    {
                        doc.Save(fileWriter);
                    }
                    return($"Written to '{OutputFilePath}' in compressed format.");
                }
                else
                {
                    using (var stringWriter = new StringWriter())
                    {
                        doc.Save(stringWriter);
                        return(stringWriter.ToString());
                    }
                }
            }
            else
            {
                if (WriteToFile)
                {
                    File.WriteAllLines(OutputFilePath, new string[] { result });
                    return($"Written to '{OutputFilePath}' in uncompressed XML format.");
                }
                else
                {
                    return(result);
                }
            }
        }
        /// <summary>
        /// Gets the object from the store
        /// </summary>
        /// <typeparam name="T">Type of the object to retrieve</typeparam>
        /// <param name="HandleName">Name from which to retrieve the object</param>
        /// <returns>Object from the store</returns>
        /// <exception cref="ArgumentException">Thrown when the HandleName is (empty)</exception>
        /// <exception cref="Exception">Thrown when the given Handle is not found in the store</exception>
        private static T GetFromStoreOrThrow <T>(string HandleName, out IStoredObject <T> storedObj)
            where T : class
        {
            HandleName = HandleNames.GetNameFrom(HandleName);

            if (String.IsNullOrWhiteSpace(HandleName))
            {
                throw new ArgumentException($"Invalid Handle name {HandleName}", nameof(HandleName));
            }

            if (!m_ObjectStore.GetByName <T>(HandleName, out storedObj))
            {
                throw new Exception($"No object {typeof(T).FullName} with handle named {HandleName} found");
            }

            return(storedObj.Object);
        }
        /// <summary>
        /// Adds the given object to the object store, and returns its handle name (name:version).
        /// Throws exceptions if anything goes wrong.
        /// </summary>
        /// <typeparam name="T">Type of the object to add</typeparam>
        /// <param name="HandleName">Name under which the object shall be stored</param>
        /// <param name="obj">The object which shall be stored</param>
        /// <param name="storedObject">[out] the stored object</param>
        /// <returns>The Handle (name:version) under which the object was stored</returns>
        private static string AddOrUpdateInStoreOrThrow <T>(string HandleName, T obj, out IStoredObject <T> storedObject, Action OnUnregister = null)
            where T : class
        {
            // Remove any invalid parts from the input
            HandleName = HandleNames.GetNameFrom(HandleName);

            if (String.IsNullOrWhiteSpace(HandleName))
            {
                throw new ArgumentException($"Invalid Handle name {HandleName}", nameof(HandleName));
            }

            if (!m_ObjectStore.AddOrUpdate <T>(HandleName, obj, out storedObject, OnUnregister))
            {
                throw new Exception("Could not add script to the object store");
            }

            return(HandleNames.ToHandle(storedObject));
        }
Beispiel #4
0
        public static object Create(
            [ExcelArgument("Name for a handle under which the script object will be stored in memory")] string HandleName,
            [ExcelArgument("The code for this script. Multiple lines are allowed.")] string[] code,
            [ExcelArgument("A handle to script option definitions as created by ExcelScript.Options.Create. Can be left blank to use defaults.")] string OptionsHandle = "",
            [ExcelArgument("An arbitrary number of handles to parameter definitions (as created by ExcelScript.Parameters.Create), which define input parameters for the script")] params string[] ParameterHandles)
        {
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }

            string _code = String.Join(Environment.NewLine, code);

            // Get Options
            XlScriptOptions xlScriptOptions = (String.IsNullOrEmpty(OptionsHandle)) ? XlScriptOptions.Default : GetFromStoreOrThrow <XlScriptOptions>(OptionsHandle);

            // Create Script object
            var script = CreateScript(xlScriptOptions);

            script.Code       = _code;
            script.ReturnType = xlScriptOptions.ReturnType;

            foreach (var parameterHandle in ParameterHandles)
            {
                var        parameterHandleName = HandleNames.GetNameFrom(parameterHandle);
                IParameter storedParameter     = GetFromStoreOrThrow <IParameter>(parameterHandleName);
                script.Parameters.Add(storedParameter);
            }

            IStoredObject <IScript> storedScript;

            if (m_ObjectStore.GetByName <IScript>(HandleName, out storedScript) && storedScript.Object.GetHashCode() == script.GetHashCode())
            {
                return(HandleNames.ToHandle(storedScript));
            }
            else
            {
                return(AddOrUpdateInStoreOrThrow <IScript>(HandleName, script, () => TryDispose(script)));
            }
        }
Beispiel #5
0
        public static object Deserialize(
            [ExcelArgument("Data input. Can either be the raw data as it was generated by ExcelScript.Serialize(), or can be a filepath from which to load the data")] string input)
        {
            var obj = InternalDeserialize(input);

            IStoredObject storedObj = (IStoredObject)obj;

            // Re-inject dependencies into the object
            var underlyingObj = storedObj.Object;

            InjectDependencies(underlyingObj);

            Type          objType = storedObj.GetType().GetGenericArguments().Single();
            IStoredObject reStoredObj;

            // todo: maybe reflect & call correct generic method?
            if (!m_ObjectStore.AddOrUpdate(storedObj.Name, underlyingObj, objType, out reStoredObj, () => TryDispose(underlyingObj)))
            {
                throw new InvalidOperationException("Object could not be re-added to the data store");
            }

            return(HandleNames.ToHandle(reStoredObj));
        }
Beispiel #6
0
        public static object Parse(
            [ExcelArgument("The code for this script. Multiple lines are allowed.")] string[] code,
            [ExcelArgument("A handle to script option definitions as created by ExcelScript.Options.Create. Can be left blank to use defaults.")] string OptionsHandle = "",
            [ExcelArgument("Name for a handle under which the script object will be stored in memory, Can be ommitted, in which case the function name will be used.")] string HandleName = "")
        {
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }

            string _code = String.Join(Environment.NewLine, code);

            // CAREFUL: This method may be run in a different AppDomain! Don't reference anything from outside of the delegate
            Func <MethodInfo[], MethodInfo> EntryMethodSelector = (methods) =>
            {
                var        _DEBUG_APPD = AppDomain.CurrentDomain.Id;
                MethodInfo result      = null;

                // When only one method is available, we'll just return that one...
                if (methods.Count() == 1)
                {
                    result = methods.Single();
                }
                else
                {
                    // Otherwise, we'll try to find a (one) function marked with an [ExcelFunction] attribute
                    var markedMethods = methods
                                        .Where(x => x.GetCustomAttribute <ExcelFunctionAttribute>() != null);

                    if (markedMethods.Count() == 0)
                    {
                        throw new ArgumentException($"Your script defines {methods.Count()} methods; please mark one of them with the [ExcelFunction] attribute, to mark which function shall be used as an entry point to your script.");
                    }

                    if (markedMethods.Count() > 1)
                    {
                        throw new ArgumentException($"Please only mark one function with an [ExcelFunction] attribute; you have currently marked {markedMethods.Count()} functions: " + String.Join(", ", markedMethods.Select(x => x.Name)));
                    }

                    result = markedMethods.Single();
                }

                return(result);
            };

            // CAREFUL: This method may be run in a different AppDomain! Don't reference anything from outside of the delegate
            Func <MethodInfo, IParameter[]> EntryMethodParameterFactory = (method =>
            {
                return(method
                       .GetParameters()
                       .Select(x =>
                {
                    var excelArgumentAttribute = x.GetCustomAttribute <ExcelArgumentAttribute>();

                    return new Parameter
                    {
                        Name = (excelArgumentAttribute == null || String.IsNullOrWhiteSpace(excelArgumentAttribute.Name)) ? x.Name : excelArgumentAttribute.Name,
                        Type = x.ParameterType,
                        IsOptional = x.IsOptional,
                        DefaultValue = x.DefaultValue,
                        Description = (excelArgumentAttribute == null || String.IsNullOrWhiteSpace(excelArgumentAttribute.Description)) ? String.Empty : excelArgumentAttribute.Description
                    };
                })
                       .ToArray());
            });

            // Create Script object
            XlScriptOptions xlScriptOptions = (String.IsNullOrEmpty(OptionsHandle)) ? XlScriptOptions.Default : GetFromStoreOrThrow <XlScriptOptions>(OptionsHandle);
            var             options         = CreateScriptingOptionsFrom(xlScriptOptions);

            options.References.Add(typeof(ExcelFunctionAttribute).Assembly);
            options.Imports.Add(typeof(ExcelFunctionAttribute).Namespace);

            var parseResult = m_ScriptFactory.ParseFromAsync <Globals>(m_GlobalsFactory, options, _code, EntryMethodSelector, EntryMethodParameterFactory).Result;
            var script      = parseResult.Script;

            script.ReturnType = xlScriptOptions.ReturnType;

            if (String.IsNullOrWhiteSpace(HandleName))
            {
                HandleName = parseResult.EntryMethodName;
            }

            IStoredObject <IScript> storedScript;

            if (m_ObjectStore.GetByName <IScript>(HandleName, out storedScript) && storedScript.Object.GetHashCode() == script.GetHashCode())
            {
                return(HandleNames.ToHandle(storedScript));
            }
            else
            {
                return(AddOrUpdateInStoreOrThrow <IScript>(HandleName, script, () => TryDispose(script)));
            }
        }