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); } }
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); } }