private void HandleMessage(string message)
        {
            List <object> data    = JsonConvert.DeserializeObject <List <object> >(message);
            string        msgType = (string)data[0];

            if (msgType == "call-reply")
            {
                int callID = Convert.ToInt32(data[1]);
                if (ActiveCalls.ContainsKey(callID))
                {
                    bool   success           = (bool)data[2];
                    object retValOrException = data[3];
                    ActiveCalls[callID].SetResult(success ? "result" : "exception",
                                                  retValOrException);
                }
                else
                {
                    throw new Error(ErrorCode.CONNECTION_ERROR,
                                    "Received a response for an unrecognized call id: " + callID);
                }
            }
            else if (msgType == "call")
            {
                int    callID     = Convert.ToInt32(data[1]);
                string methodName = (string)data[2];
                if (RegisteredFunctions.ContainsKey(methodName))
                {
                    Delegate        nativeMethod = RegisteredFunctions[methodName];
                    ParameterInfo[] paramInfo    = nativeMethod.Method.GetParameters();
                    if (paramInfo.Length != data.Count - 3)
                    {
                        throw new Error(ErrorCode.INVALID_ARGUMENT,
                                        "Incorrect number of arguments for method: " + methodName +
                                        ". Expected: " + paramInfo.Length + ". Got: " +
                                        (data.Count - 3));
                    }
                    List <object> parameters = new List <object>();
                    for (int i = 0; i < paramInfo.Length; i++)
                    {
                        parameters.Add(ConversionUtils.CastJObject(
                                           data[i + 3], paramInfo[i].ParameterType));
                    }

                    object returnValue = null;
                    object exception   = null;
                    bool   success     = true;

                    try
                    {
                        returnValue = nativeMethod.DynamicInvoke(parameters.ToArray());
                    }
                    catch (Exception e)
                    {
                        exception = e;
                        success   = false;
                    }

                    if (!IsOneWay(methodName))
                    {
                        // Send call-reply message.
                        List <object> callReplyMessage = new List <object>();
                        callReplyMessage.Add("call-reply");
                        callReplyMessage.Add(callID);
                        callReplyMessage.Add(success);

                        if (!success)
                        {
                            callReplyMessage.Add(exception);
                        }
                        else if (nativeMethod.Method.ReturnType != typeof(void))
                        {
                            callReplyMessage.Add(returnValue);
                        }

                        Connection.Send(JsonConvert.SerializeObject(callReplyMessage));
                    }
                }
                else
                {
                    throw new Error(ErrorCode.CONNECTION_ERROR,
                                    "Received a call for an unregistered method: " + methodName);
                }
            }
            else
            {
                throw new Error(ErrorCode.CONNECTION_ERROR, "Unknown message type: " + msgType);
            }
        }
Exemple #2
0
        internal void SetResult(string eventName, object argument)
        {
            // TODO(rryk): Handle the case when result/error/exception arrives before the handlers
            // are set. Essentially this involves setting a flag that we do have a result and
            // calling the callbacks immediately after they are added via On(...) method.
            if (eventName == "result")
            {
                // Cast return object to a specific type accepted by each individual result handler.
                foreach (Delegate resultDelegate in OnResult)
                {
                    Type retValueType = resultDelegate.Method.GetParameters()[0].ParameterType;
                    resultDelegate.DynamicInvoke(
                        ConversionUtils.CastJObject(argument, retValueType));
                }

                foreach (Delegate excResultDelegate in OnExcResult)
                {
                    Type retValueType = excResultDelegate.Method.GetParameters()[1].ParameterType;
                    excResultDelegate.DynamicInvoke(
                        null, ConversionUtils.CastJObject(argument, retValueType));
                }
            }
            else if (eventName == "exception")
            {
                // Cast exception object to a specific type accepted by each individual result
                // handler.
                foreach (Delegate exceptionDelegate in OnException)
                {
                    Type retValueType = exceptionDelegate.Method.GetParameters()[0].ParameterType;
                    exceptionDelegate.DynamicInvoke(
                        ConversionUtils.CastJObject(argument, retValueType));
                }

                foreach (Delegate excResultDelegate in OnExcResult)
                {
                    Type exceptionType = excResultDelegate.Method.GetParameters()[0].ParameterType;
                    excResultDelegate.DynamicInvoke(
                        ConversionUtils.CastJObject(argument, exceptionType), null);
                }

                // If no handlers are set, yet exception was returned - raise it.
                if (OnException.Count == 0 && OnExcResult.Count == 0)
                {
                    throw new Error(ErrorCode.GENERIC_ERROR, "Received unhandled exception from " +
                                    "the remote end: " + argument.ToString());
                }
            }
            else if (eventName == "error")
            {
                if (argument.GetType() != typeof(string))
                {
                    throw new Error(ErrorCode.INVALID_ARGUMENT,
                                    "Argument for 'error' event must be a string");
                }
                OnError((string)argument);
            }
            else
            {
                throw new Error(ErrorCode.INVALID_ARGUMENT, "Invalid event name: " + eventName);
            }
        }