/// <summary> /// Gets the declaration data of a static function by searching for the give signature (<paramref name="functionIdentifier"/> and <paramref name="parameterTypes"/>) /// in the LibraryPlugin with the given <paramref name="libraryPluginIdentifier"/>. /// </summary> /// <param name="libraryPluginIdentifier">the synery identifier of the plugin</param> /// <param name="functionIdentifier">the long name of the function including the namespace</param> /// <param name="parameterTypes">the data typs of the parameters (the correct order is important!)</param> /// <returns></returns> public IStaticExtensionFunctionData GetStaticFunctionDataBySignature(string libraryPluginIdentifier, string functionIdentifier, Type[] parameterTypes) { var libraryPluginData = (from i in _AvailablePlugins where i.Key.SyneryIdentifier == libraryPluginIdentifier select i.Value).FirstOrDefault(); if (libraryPluginData == null) { throw new LibraryPluginManagerException(this, String.Format( "Error while calling a static extension function. A LibraryPlugin with the given SyneryIdentifier='{0}' wasn't found.", libraryPluginIdentifier)); } else { IStaticExtensionFunctionData functionData = FindFunctionDeclaration(libraryPluginData, functionIdentifier, parameterTypes); if (functionData == null) { string paramTypeNames = string.Join(",", parameterTypes.Select(p => p.Name)); throw new LibraryPluginManagerException(this, String.Format( "No static extension function with the signature {0}.{1}({2}) was found.", libraryPluginIdentifier, functionIdentifier, paramTypeNames)); } return(functionData); } }
public IValue RunWithResult(SyneryParser.LibraryPluginFunctionCallContext context) { string libraryPluginIdentifier; string functionIdentifier; string fullIdentifier = context.libraryPluginFunctionCallIdentifier().ExternalLibraryIdentifier().GetText(); // split the identifier bool success = FunctionHelper.FragmentLibraryPluginIdentifier(fullIdentifier, out libraryPluginIdentifier, out functionIdentifier); if (success == false) { throw new SyneryInterpretationException(context.libraryPluginFunctionCallIdentifier(), "Wasn't able to fragment the library plugin function identifier. It doesn't have the expected format."); } // validate the identifier if (String.IsNullOrEmpty(libraryPluginIdentifier)) { throw new SyneryInterpretationException(context, "The library plugin identifier is empty."); } if (String.IsNullOrEmpty(functionIdentifier)) { throw new SyneryInterpretationException(context, "The function identifier is empty."); } // get the parameters IList <IValue> listOfParameters = FunctionHelper.GetListOfParameterValues(Controller, context.expressionList()); Type[] listOfParameterTypes = listOfParameters.Select(p => p.Type.UnterlyingDotNetType).ToArray(); object[] listOfParameterValues = listOfParameters.Select(p => p.Value).ToArray(); // find the function declaration IStaticExtensionFunctionData functionDeclaration = Memory.LibraryPluginManager.GetStaticFunctionDataBySignature(libraryPluginIdentifier, functionIdentifier, listOfParameterTypes); object result = null; try { // execute the function result = Memory.LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, listOfParameterValues); } catch (Exception ex) { // create a Synery exception that can be caught by the Synery developer LibraryPluginExceptionRecord syneryException = new LibraryPluginExceptionRecord(); syneryException.Message = ExceptionHelper.GetNestedExceptionMessages(ex); syneryException.FullIdentifier = fullIdentifier; syneryException.LibraryPluginIdentifier = libraryPluginIdentifier; Controller.HandleSyneryEvent(context, syneryException.GetAsSyneryValue()); } return(new TypedValue(TypeHelper.GetSyneryType(functionDeclaration.ReturnType), result)); }
public IExpressionValue RunWithResult(SyneryParser.RequestLibraryPluginFunctionCallContext context, QueryMemory queryMemory) { string libraryPluginIdentifier; string functionIdentifier; string fullIdentifier = context.libraryPluginFunctionCallIdentifier().ExternalLibraryIdentifier().GetText(); // split the identifier bool success = FunctionHelper.FragmentLibraryPluginIdentifier(fullIdentifier, out libraryPluginIdentifier, out functionIdentifier); if (success == false) { throw new SyneryInterpretationException(context.libraryPluginFunctionCallIdentifier(), "Wasn't able to fragment the library plugin function identifier. It doesn't have the expected format."); } // validate the identifer if (String.IsNullOrEmpty(libraryPluginIdentifier)) { throw new SyneryInterpretationException(context, "The library plugin identifer is empty."); } if (String.IsNullOrEmpty(functionIdentifier)) { throw new SyneryInterpretationException(context, "The function identifer is empty."); } // get the parameters IEnumerable <IExpressionValue> listOfParameters = FunctionHelper.GetListOfParameterExpressionValues(Controller, queryMemory, context.requestExpressionList()); Type[] listOfParameterTypes = listOfParameters.Select(p => p.ResultType.UnterlyingDotNetType).ToArray(); IEnumerable <Expression> listOfParameterExpressions = listOfParameters.Select(p => p.Expression); // find the function declaration IStaticExtensionFunctionData functionDeclaration = Memory.LibraryPluginManager.GetStaticFunctionDataBySignature(libraryPluginIdentifier, functionIdentifier, listOfParameterTypes); // check whether the function has a return // functions without a return value aren't supported inside of a request statement if (functionDeclaration.ReturnType == null) { throw new SyneryInterpretationException(context, String.Format("Cannot call a function without a return from a query. Please chose a function instead of '{0}.{1}' that has a return value.", libraryPluginIdentifier, functionIdentifier)); } // build the LINQ expression for calling the function from inside the LINQ expression tree Expression functionCallExpression = BuildExpression(functionDeclaration, listOfParameterExpressions); return(new ExpressionValue( expression: functionCallExpression, resultType: TypeHelper.GetSyneryType(functionDeclaration.ReturnType) )); }
public void Calling_Function_Without_Parameters_And_With_A_String_ReturnValue_Works() { FirstDummyStaticExtension extension = new FirstDummyStaticExtension(); string expectedResult = extension.SecondMethod(); IStaticExtensionFunctionData functionDeclaration = _LibraryPluginManager.GetStaticFunctionDataBySignature("First", "SecondMethod", new Type[] { }); object result = _LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, new object[] {}); Assert.AreEqual(expectedResult, result); }
/// <summary> /// Executes a static function that returns a primitive value like string, int, bool etc. /// </summary> /// <param name="functionData"></param> /// <param name="listOfParameters">parameter values (the correct order is important!)</param> /// <returns>the return value or null if the function has no return value</returns> public object CallStaticFunctionWithPrimitiveReturn(IStaticExtensionFunctionData functionData, object[] listOfParameters) { object result; Type[] parameterTypes = (from p in functionData.Parameters select p.Type).ToArray(); IList <object> parameterValues = listOfParameters.ToList(); while (parameterValues.Count() < parameterTypes.Count()) { // Optional parameters must be set as "Missing". // Otherwise the Invoke-method will throw an exception because the lenght of the parameter array doesn't match the method signature. parameterValues.Add(Type.Missing); } Type staticExtensionType = functionData.StaticExtension.GetType(); MethodInfo method = staticExtensionType.GetMethod(functionData.MethodName, parameterTypes); if (method == null) { throw new LibraryPluginManagerException(this, String.Format( "Couldn't resolve a method with the name='{0}' and {1} parameter(s) (type order: {2}).", functionData.MethodName, functionData.Parameters.Count, string.Join(",", functionData.Parameters.Select(p => p.Type.Name)))); } try { // call the function result = method.Invoke(functionData.StaticExtension, parameterValues.ToArray()); } catch (Exception ex) { throw new LibraryPluginManagerException(this, String.Format( "An unexpected error occured while calling the static extension function with name='{0}'. The called method is named '{1}' and has {2} parameter(s) (type order: {3}).", functionData.FullSyneryIdentifier, functionData.MethodName, functionData.Parameters.Count, string.Join(",", functionData.Parameters.Select(p => p.Type.Name))), ex); } if (functionData.ReturnType != null) { return(result); } else { return(null); } }
public void Calling_Function_With_Alternative_Name() { List <IValue> parameters = new List <IValue>() { new TypedValue(TypeHelper.GetSyneryType(typeof(string)), "This is a test."), }; FourthDummyStaticExtension extension = new FourthDummyStaticExtension(); string expectedResult = extension.SecondMethod((string)parameters[0].Value); IStaticExtensionFunctionData functionDeclaration = _LibraryPluginManager.GetStaticFunctionDataBySignature("First", "FirstLevelNamespace.SecondLevelNamespace.FirstMethodWithAlternativeName", parameters.Select(p => p.Type.UnterlyingDotNetType).ToArray()); object result = _LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, parameters.Select(p => p.Value).ToArray()); Assert.AreEqual(expectedResult, result); }
public void Calling_Overloaded_Function_With_DateTime_Parameter_Works() { List <IValue> parameters = new List <IValue>() { new TypedValue(TypeHelper.GetSyneryType(typeof(DateTime)), new DateTime(1987, 12, 15, 22, 30, 0)), }; FirstDummyStaticExtension extension = new FirstDummyStaticExtension(); string expectedResult = extension.OverloadedMethod((DateTime)parameters[0].Value); IStaticExtensionFunctionData functionDeclaration = _LibraryPluginManager.GetStaticFunctionDataBySignature("First", "OverloadedMethod", parameters.Select(p => p.Type.UnterlyingDotNetType).ToArray()); object result = _LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, parameters.Select(p => p.Value).ToArray()); Assert.AreEqual(expectedResult, result); }
public void Calling_Function_With_One_Parameter_And_With_A_String_ReturnValue_Works() { List <IValue> parameters = new List <IValue>() { new TypedValue(TypeHelper.GetSyneryType(typeof(string)), "This is a test."), }; FirstDummyStaticExtension extension = new FirstDummyStaticExtension(); string expectedResult = extension.ThirdMethod((string)parameters[0].Value); IStaticExtensionFunctionData functionDeclaration = _LibraryPluginManager.GetStaticFunctionDataBySignature("First", "ThirdMethod", parameters.Select(p => p.Type.UnterlyingDotNetType).ToArray()); object result = _LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, parameters.Select(p => p.Value).ToArray()); Assert.AreEqual(expectedResult, result); }
public void Calling_Function_Without_Parameters_And_Without_ReturnValue_Works() { // the dummy plugin creates a textfile that indicates whether the function was executed // the test was successfull if the textfile exists string expectedExistingFilePath = Path.Combine(_LibraryPluginRuntimeTestPath, "FirstMethod.txt"); if (File.Exists(expectedExistingFilePath)) { throw new Exception("The test-file already exists before starting the test"); } IStaticExtensionFunctionData functionDeclaration = _LibraryPluginManager.GetStaticFunctionDataBySignature("First", "FirstMethod", new Type[] {}); _LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, new object[] {}); Assert.IsTrue(File.Exists(expectedExistingFilePath)); }
/// <summary> /// Builds an expression that looks like this: /// Memory.LibraryPluginManager.CallStaticFunctionWithPrimitiveReturn(functionDeclaration, listOfParameterValues) /// </summary> /// <param name="functionData"></param> /// <param name="listOfParameterExpressions"></param> /// <param name="context"></param> /// <returns></returns> private Expression BuildExpression(IStaticExtensionFunctionData functionData, IEnumerable <Expression> listOfParameterExpressions) { // cast all parameters to objects because LINQ requires all parameter-array items to be of type object IEnumerable <Expression> listOfObjectParameterExpressions = listOfParameterExpressions.Select(ex => Expression.Convert(ex, typeof(object))); MethodInfo executeFunctionMethod = typeof(ILibraryPluginManager) .GetMethod("CallStaticFunctionWithPrimitiveReturn", new Type[] { typeof(IStaticExtensionFunctionData), typeof(object[]) }); Expression libraryPluginManagerExpression = Expression.Constant(Memory.LibraryPluginManager); Expression paramFunctionDataExpression = Expression.Constant(functionData, typeof(IStaticExtensionFunctionData)); Expression paramListOfParametersExpression = Expression.NewArrayInit(typeof(object), listOfObjectParameterExpressions); Expression methodCallExpression = Expression.Call( libraryPluginManagerExpression, executeFunctionMethod, paramFunctionDataExpression, paramListOfParametersExpression); return(methodCallExpression); }