Beispiel #1
0
        /// <summary>
        /// 调用处理RpcRequest的方法
        /// </summary>
        /// <param name="requestContext">待处理的请求方法</param>
        /// <param name="rpcContext">Rpc方法中获得的可选上下文</param>
        /// <param name="callback">回调方法</param>
        /// <returns></returns>
        public JsonRpcResponseContext Handle(JsonRpcRequestContext requestContext, Object rpcContext = null, Action <JsonRpcResponseContext> callback = null)
        {
            //回调函数初始
            if (callback == null)
            {
                callback = delegate(JsonRpcResponseContext item) { }
            }
            ;

            //添加到线程Id->上下文集合中
            AddRpcContext(rpcContext);
            //初始化当前线程数据上下文
            //JsonRpcDataContext.GetOrInitCurrentContext();
            //将请求上下文Tags赋值到线程上下文中
            foreach (var key in requestContext.Tags.Keys)
            {
                JsonRpcDataContext.SetContextItem(key, requestContext.Tags[key]);
            }

            #region 预处理&出错则回调直接返回
            var preProcessingException = PreProcess(requestContext, rpcContext);
            if (preProcessingException != null)
            {
                var response = new JsonRpcResponseContext()
                {
                    Error = preProcessingException,
                    Id    = requestContext.Id
                };
                callback.Invoke(response);
                CompletedProcess(requestContext, response, rpcContext);
                return(response);
            }
            #endregion

            #region 获取和验证请求的委托与meta信息
            //当前请求方法对应的meta信息
            SMDService metaData = null;
            //当前请求方法对应的反射委托
            Delegate handle = null;
            //根据请求方法,获取方法对应的委托
            var haveDelegate = Handlers.TryGetValue(requestContext.Method, out handle);
            //根据请求方法,获取方法对应的meta信息
            var haveMetadata = MetaData.Services.TryGetValue(requestContext.Method, out metaData);
            if (haveDelegate == false || haveMetadata == false || metaData == null || handle == null)
            {
                var response = new JsonRpcResponseContext()
                {
                    Result = null,
                    Error  = new JsonRpcException(-32601, "方法未找到", "此方法 " + requestContext.Method + " 不存在或未部署", requestContext),
                    Id     = requestContext.Id
                };
                callback.Invoke(response);
                CompletedProcess(requestContext, response, rpcContext);
            }
            #endregion

            #region 参数获取与校验
            bool isJObject = requestContext.Params is JObject;
            bool isJArray  = requestContext.Params is JArray;

            //请求方法参数
            object[] parameters = null;

            //metaData是否包含异常
            bool expectsRefException = false;

            //metaData 参数数量
            var metaDataParamCount = metaData.parameters.Count(p => p != null);

            //获取当前请求上下问参数集合
            var paramCollection = requestContext.Params as ICollection;
            int paramCount = 0, loopCount = 0;
            if (paramCollection != null)
            {
                paramCount = loopCount = paramCollection.Count;
            }
            //在请求参数与metaData参数相差一情况下,判断metaData最后参数是否为异常
            if (paramCount == metaDataParamCount - 1 && metaData.parameters[metaDataParamCount - 1].ObjectType.Name.Contains(typeof(JsonRpcException).Name))
            {
                paramCount++;
                expectsRefException = true;
            }
            //初始化请求参数集合大小
            parameters = new object[paramCount];

            //根据请求参数不同类型,填充参数集合
            if (isJArray)
            {
                var jArray = requestContext.Params as JArray;
                for (int i = 0; i < loopCount; i++)
                {
                    parameters[i] = ConvetParameter(jArray[i], metaData.parameters[i]);
                }
            }
            else if (isJObject)
            {
                var jObject   = requestContext.Params as JObject;
                var tokenDict = jObject as IDictionary <string, JToken>;
                parameters = new object[metaData.parameters.Length];

                //将请求参数与服务定义参数进行比较
                for (int i = 0; i < metaData.parameters.Length; i++)
                {
                    if (tokenDict.ContainsKey(metaData.parameters[i].Name) == false)
                    {
                        var response = new JsonRpcResponseContext()
                        {
                            Error = ProcessException(requestContext,
                                                     new JsonRpcException(-32602, "无效参数", string.Format("参数 '{0}' 未定义", metaData.parameters[i].Name), requestContext)),
                            Id = requestContext.Id
                        };
                    }
                    //获取请求参数
                    parameters[i] = ConvetParameter(jObject[metaData.parameters[i].Name], metaData.parameters[i]);
                }
            }

            //请求参数小于metaData参数,可能包含可选参数
            if (parameters.Length < metaDataParamCount && metaData.defaultValues.Length > 0)
            {
                //请求参数提供的数量
                var suppliedParamsCount = parameters.Length;

                //非Rpc设置的可选参数数量,缺失的参数数量
                var missingParamsCount = metaDataParamCount - parameters.Length;

                //调整可选参数数组大小,用于包含所有可选参数
                Array.Resize(ref parameters, parameters.Length + missingParamsCount);

                //将所有参数填充到parameters中
                for (int paramIndex = parameters.Length - 1, defaultIndex = metaData.defaultValues.Length - 1;
                     paramIndex >= suppliedParamsCount && defaultIndex >= 0; paramIndex--, defaultIndex--)
                {
                    parameters[paramIndex] = metaData.defaultValues[defaultIndex].Value;
                }

                if (missingParamsCount > metaData.defaultValues.Length)
                {
                    var response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext,
                                                 new JsonRpcException(-32602, "无效参数", string.Format("缺省参数数量 {0} 不足以填充所缺失的参数数量 {1}",
                                                                                                    metaData.defaultValues.Length, missingParamsCount), requestContext)),
                        Id = requestContext.Id
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }
            }
            if (parameters.Length != metaDataParamCount)
            {
                var response = new JsonRpcResponseContext()
                {
                    Error = ProcessException(requestContext,
                                             new JsonRpcException(-32602, "无效参数", string.Format("应接收 {0} 个参数,实际接收到 {1}",
                                                                                                metaData.parameters.Length, parameters.Length), requestContext)),
                    Id = requestContext.Id
                };
                callback.Invoke(response);
                CompletedProcess(requestContext, response, rpcContext);
                return(response);
            }
            #endregion

            #region 调用
            try
            {
                //将回调存储到当前线程中,,便于从GetAsyncCallback中获得以进行回调
                Thread.SetData(Thread.GetNamedDataSlot(THREAD_CALLBACK_SLOT_NAME), callback);
                //调用请求方法对应委托并传入参数
                var results = handle.DynamicInvoke(parameters);

                //当前线程包含异常
                if (Task.CurrentId.HasValue && rpcExceptions.TryRemove(Task.CurrentId.Value, out JsonRpcException contextException))
                {
                    var response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, contextException), Id = requestContext.Id
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }

                var lastParam = parameters.LastOrDefault();
                if (expectsRefException && lastParam != null && lastParam is JsonRpcException)
                {
                    var response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, lastParam as JsonRpcException),
                        Id    = requestContext.Id
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }

                //返回结果
                var reponse = new JsonRpcResponseContext()
                {
                    Result = results
                };
                CompletedProcess(requestContext, reponse, requestContext);
                return(reponse);
            }
            catch (Exception ex)
            {
                JsonRpcResponseContext response = null;
                //系统委托调用异常(参数不匹配)
                if (ex is TargetParameterCountException)
                {
                    response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, new JsonRpcException(-32602, "参数不匹配", ex, rpcContext))
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }
                //业务异常
                if (ex is JsonRpcException)
                {
                    response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, new JsonRpcException(-32603, "内部错误", ex.InnerException, rpcContext)),
                        Id    = requestContext.Id
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }
                //内部异常为业务异常
                if (ex.InnerException != null && ex.InnerException is JsonRpcException)
                {
                    response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, ex.InnerException as JsonRpcException)
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }
                //内部异常
                else if (ex.InnerException != null)
                {
                    response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, new JsonRpcException(-32603, "内部错误", ex.InnerException, rpcContext))
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }
                //其他异常,封装返回
                else
                {
                    response = new JsonRpcResponseContext()
                    {
                        Error = ProcessException(requestContext, new JsonRpcException(-32603, "内部错误", ex, rpcContext))
                    };
                    callback.Invoke(response);
                    CompletedProcess(requestContext, response, rpcContext);
                    return(response);
                }
            }
            finally
            {
                RemoveRpcContext();
            }
            #endregion
        }
Beispiel #2
0
        public void AddService(string method, Dictionary <string, Type> parameters, Dictionary <string, object> defaultValues)
        {
            var newService = new SMDService(transport, "JSON-RPC-2.0", parameters, defaultValues);

            Services.Add(method, newService);
        }