示例#1
0
        /// <summary>
        /// Generates a client function for the <paramref name="funcName"/>. Optional <paramref name="typeMapping"/> string
        /// may be used to specify data omission and reordering options.
        /// </summary>
        /// <returns>The generated client function.</returns>
        /// <param name="serviceName">Service that contains the wrapped function.</param>
        /// <param name="functionName">Name of the function that should be wrapped.</param>
        public virtual ClientFunction GenerateClientFunction(string serviceName, string functionName)
        {
            if (!SinTD.SINFONIServices.ContainsService(serviceName))
            {
                throw new ServiceNotRegisteredException(serviceName);
            }

            var service = SinTD.SINFONIServices.GetService(serviceName);

            if (!service.ContainsServiceFunction(functionName))
            {
                throw new ServiceNotRegisteredException(functionName);
            }

            return((ClientFunction) delegate(object[] parameters)
            {
                SINFONIService registeredService = SinTD.SINFONIServices.GetService(serviceName);
                ServiceFunctionDescription registeredServiceFunction = registeredService.GetServiceFunction(functionName);

                if (!registeredServiceFunction.CanBeCalledWithParameters(parameters))
                {
                    throw new ParameterMismatchException(
                        "Could not call Service Function " + serviceName + "." + functionName
                        + ". The provided parameters can not be mapped to the parameters specified in the IDL.");
                }
                object[] callParameters = new object[parameters.Length];
                for (var i = 0; i < parameters.Length; i++)
                {
                    SinTDType expectedParameterType = registeredServiceFunction.Parameters.ElementAt(i).Value;
                    callParameters[i] = expectedParameterType.AssignValuesFromObject(parameters[i]);
                }
                return CallClientFunction(serviceName + "." + functionName, callParameters);
            });
        }
示例#2
0
        /// <summary>
        /// Creates a SinTDTyped object and stores it under the name specified in the IDL for the corresponding parameter.
        /// The created Parameter is added to the list of parameters for the currently parsed service function object.
        /// </summary>
        /// <param name="param">String defining name and type of the parameter</param>
        /// <param name="functionDescription">Service Function object to which the parameter should be added</param>
        private void createParameterForServiceFunction(string param, ServiceFunctionDescription functionDescription)
        {
            string[] values = splitDeclarationInNameAndType(param);

            SinTDType paramType = getSinTDType(values[0].Trim());
            string    paramName = values[1].Trim();

            functionDescription.Parameters.Add(paramName, paramType);
        }
示例#3
0
        public void CallShouldBeValidForArrayParameters()
        {
            SinTDArray parameterArray = new SinTDArray();
            parameterArray.elementType = i32;

            var serviceFunction = new ServiceFunctionDescription("arrayFunction", new SinTDType("void"));
            serviceFunction.Parameters.Add("arrayParam", parameterArray);
            service.serviceFunctions.Add("arrayFunction", serviceFunction);
            var clientFunction = connection.GenerateClientFunction("service", "arrayFunction");
            Assert.DoesNotThrow(() => clientFunction(new int[] {1, 2, 3, 4}));
        }
示例#4
0
        public void CallShouldBeValidForMapParameters()
        {
            SinTDMap parameterMap = new SinTDMap();
            parameterMap.elementType = i32;
            parameterMap.keyType = SinTD_string;

            var serviceFunction = new ServiceFunctionDescription("mapFunction", new SinTDType("void"));
            serviceFunction.Parameters.Add("mapParam", parameterMap);
            service.serviceFunctions.Add("mapFunction", serviceFunction);
            var clientFunction = connection.GenerateClientFunction("service", "mapFunction");
            Assert.DoesNotThrow(() => clientFunction(new Dictionary<string, int> {
                {"first", 1},
                {"second", 2}
            }));
        }
示例#5
0
        /// <summary>
        /// Parses parameters given for a service function in the IDL.
        /// </summary>
        /// <param name="parameterDefinition">String defining all parameters of a service funtion in the IDL</param>
        /// <param name="functionDescription">The ServiceFunction object for which the parameters are created</param>
        private void parseParameters(string parameterDefinition, ServiceFunctionDescription functionDescription)
        {
            if (parameterDefinition.Length == 0)
            {
                return;
            }

            // Both different parameters and key-and-value definitions of maps are separated by commata.
            // Replace the commata separating the parameters by another delimiter to avoid ambiguity and still
            // allow the MapParser to work correctly
            parameterDefinition = replaceMapKeyValueDelimiter(parameterDefinition);
            string[] parameters = parameterDefinition.Split(';');
            foreach (string param in parameters)
            {
                createParameterForServiceFunction(param.Trim(), functionDescription);
            }
        }
示例#6
0
        /// <summary>
        /// Interprets a line of the IDL as service function definition and creates one of it from the entry
        /// </summary>
        /// <param name="line">Line as read from the IDL</param>
        /// <param name="lineNumber">Line number within IDL</param>
        private void parseServiceFunctionDefinition(string line, int lineNumber)
        {
            // Check syntax of the line. If the parameter list cannot be retrieved correctly from the
            // paranthese, or the definition is not finished by a semicolon, throw exception
            if (!(line.Contains(';') &&
                  line.Contains('(') &&
                  line.Contains(')')))
            {
                throw new IDLParseException(line, lineNumber);
            }

            int indexOfOpenPar  = line.IndexOf('(');
            int indexOfClosePar = line.IndexOf(')');

            string parameterDefinition = line.Substring(indexOfOpenPar + 1, indexOfClosePar - (indexOfOpenPar + 1));
            string nameAndType         = line.Substring(0, indexOfOpenPar);

            ServiceFunctionDescription newServiceFunction = createTypedServiceFunction(nameAndType);

            parseParameters(parameterDefinition, newServiceFunction);
            currentlyParsedService.serviceFunctions.Add(newServiceFunction.Name, newServiceFunction);
        }
示例#7
0
        /// <summary>
        /// Is called when Connection receives a message that is identified as service call. Upon receiving a call,
        /// SINFONI will check whether the called service exists, what parameters it expects and which local function
        /// implements the service. If the service exists and the parameter types match, the local function called
        /// and a call-reply object with the result is sent back to the client
        /// </summary>
        /// <param name="callMessage">The deserialized message object that was received by the connection</param>
        private void HandleCall(IMessage callMessage)
        {
            int    callID     = callMessage.ID;
            string methodName = callMessage.MethodName;

            string[] serviceDescription = methodName.Split('.');

            Delegate nativeMethod = null;

            lock (registeredFunctions)
            {
                if (registeredFunctions.ContainsKey(methodName))
                {
                    nativeMethod = registeredFunctions[methodName];
                }
            }

            if (nativeMethod != null)
            {
                object[] parameters;
                try
                {
                    var args      = callMessage.Parameters;
                    var callbacks = callMessage.Callbacks;
                    var paramInfo = new List <ParameterInfo>(nativeMethod.Method.GetParameters());
                    parameters = ConvertParameters(methodName, args, callbacks, paramInfo);
                }
                catch (Exception e)
                {
                    SendException(callID, e.Message);
                    return;
                }

                if (!IsOneWay(methodName))
                {
                    object returnValue = null;
                    object exception   = null;
                    bool   success     = true;
                    try
                    {
                        // Super Evil Hack Here! Existing unit tests assume that WSJON serializes in a fixed format that
                        // originates from serializing the native types correctly. Also, the tests do not take into account
                        // any SinTD from any IDL. To make them work, we have to pretend that there is no ServiceRegistry
                        // maintaining any service description, but bypass type check and automatic SinTD Conversion
                        // by setting service Registry to null
                        if (SinTD == null)
                        {
                            returnValue = nativeMethod.DynamicInvoke(parameters);
                        }
                        else
                        {
                            ServiceFunctionDescription service = SinTD.SINFONIServices
                                                                 .GetService(serviceDescription[0])
                                                                 .GetServiceFunction(serviceDescription[1]);
                            returnValue = service.ReturnType.AssignValuesFromObject(nativeMethod.DynamicInvoke(parameters));
                        }
                    }
                    catch (Exception e)
                    {
                        exception = e;
                        success   = false;
                    }
                    SendResponse(callID, nativeMethod, success, returnValue, exception);
                }
                else
                {
                    nativeMethod.DynamicInvoke(parameters);
                }
            }
            else
            {
                SendException(callID, "Method " + methodName + " is not registered");
                return;
            }
        }
示例#8
0
        /// <summary>
        /// Creates a SinTDTyped object and stores it under the name specified in the IDL for the corresponding parameter.
        /// The created Parameter is added to the list of parameters for the currently parsed service function object.
        /// </summary>
        /// <param name="param">String defining name and type of the parameter</param>
        /// <param name="functionDescription">Service Function object to which the parameter should be added</param>
        private void createParameterForServiceFunction(string param, ServiceFunctionDescription functionDescription)
        {
            string[] values = splitDeclarationInNameAndType(param);

            SinTDType paramType = getSinTDType(values[0].Trim());
            string paramName = values[1].Trim();
            functionDescription.Parameters.Add(paramName, paramType);
        }
示例#9
0
        /// <summary>
        /// Parses parameters given for a service function in the IDL.
        /// </summary>
        /// <param name="parameterDefinition">String defining all parameters of a service funtion in the IDL</param>
        /// <param name="functionDescription">The ServiceFunction object for which the parameters are created</param>
        private void parseParameters(string parameterDefinition, ServiceFunctionDescription functionDescription)
        {
            if (parameterDefinition.Length == 0)
                return;

            // Both different parameters and key-and-value definitions of maps are separated by commata.
            // Replace the commata separating the parameters by another delimiter to avoid ambiguity and still
            // allow the MapParser to work correctly
            parameterDefinition = replaceMapKeyValueDelimiter(parameterDefinition);
            string[] parameters = parameterDefinition.Split(';');
            foreach (string param in parameters)
            {
                createParameterForServiceFunction(param.Trim(), functionDescription);
            }
        }
示例#10
0
 public void CallShouldBeValidForStructParameters()
 {
     var serviceFunction = new ServiceFunctionDescription("structFunction", new SinTDType("void"));
     serviceFunction.Parameters.Add("structParam", intStruct);
     service.serviceFunctions.Add("structFunction", serviceFunction);
     var clientFunction = connection.GenerateClientFunction("service", "structFunction");
     Assert.DoesNotThrow(() => clientFunction(new testStruct { x = 1, y = 1 }));
 }
示例#11
0
        public void Setup()
        {
            SinTDInstance = new SinTD();
            SinTDInstance.SINFONIServices = new ServiceRegistry();

            i32 = SinTDInstance.GetSinTDType("i32");
            SinTD_string = SinTDInstance.GetSinTDType("string");

            intStruct = new SinTDStruct("intStruct");
            intStruct.members["x"] = i32;
            intStruct.members["y"] = i32;

            serviceFunction = new ServiceFunctionDescription("function", new SinTDType("void"));
            serviceFunction.Parameters.Add("intParameter", i32);
            serviceFunction.Parameters.Add("stringParameter", SinTD_string);

            service = new SINFONIService("service");
            service.serviceFunctions.Add("function", serviceFunction);

            SinTDInstance.SINFONIServices.services.Add("service", service);
            connection = new TestConnection();
            connection.SinTD = SinTDInstance;
        }