Exemplo n.º 1
0
        /// <summary>
        /// Invokes an operation method.
        /// </summary>
        /// <typeparam name="TT">The task return type.</typeparam>
        /// <param name="method">The method.</param>
        /// <param name="args">The arguments.</param>
        /// <param name="returnType">The real return type.</param>
        /// <returns></returns>
        protected virtual async Task <TT> InvokeOperationAsync <TT>(MethodInfo method, object[] args, Type returnType)
        {
            // build arguments
            Dictionary <string, object> argsPayload = new Dictionary <string, object>();

            ParameterInfo[] argsMethod = method.GetParameters();

            for (int i = 0; i < args.Length; i++)
            {
                argsPayload[argsMethod[i].Name] = args[i];
            }

            // create request
            RpcRequest req = new RpcRequest(_contractAttr.Name != null ? _contractAttr.Name : _typeInfo.Name, method.Name, argsPayload);

            // serialize
            byte[]    requestBody = new ProtobufRpcSerializer().SerializeRequest(req);
            RpcHeader header      = new RpcHeader(RpcHeader.HEADER_VERSION, ProtobufRpcSerializer.SerializerName, RpcMessageType.Single);

            // create headers
            IDictionary <string, object> headers = new Dictionary <string, object>()
            {
                { RpcHeader.HEADER_NAME, header.ToString() }
            };

            // ask or send
            if (method.GetCustomAttribute <RpcOperationAttribute>().NoReply)
            {
                // send operation
                await _channel.SendAsync(requestBody, headers);

                return(default(TT));
            }
            else
            {
                Envelope res = await _channel.AskAsync(requestBody, _configuration.Timeout, headers);

                // transform response
                byte[] responseBody = res.Body;

                // try and get response header
                if (!res.Headers.TryGetValue(RpcHeader.HEADER_NAME, out object resHeaderData))
                {
                    throw new InvalidOperationException("The response envelope is not a valid RPC message");
                }

                RpcHeader resHeader = new RpcHeader(Encoding.UTF8.GetString(resHeaderData as byte[]));

                // deserialize response
                if (!RpcSerializer.Serializers.TryGetValue(resHeader.Serializer, out IRpcSerializer deserializer))
                {
                    throw new NotSupportedException("The response serializer is not supported");
                }

                // deserialize
                RpcResponse resPayload = null;

                if (method.ReturnType == typeof(Task))
                {
                    // deserialize
                    resPayload = deserializer.DeserializeResponse(responseBody, typeof(void));

                    // return result
                    if (resPayload.IsSuccess)
                    {
                        return((TT)(object)true);
                    }
                }
                else
                {
                    // deserialize
                    Type taskType = method.ReturnType.GetGenericArguments()[0];
                    resPayload = deserializer.DeserializeResponse(responseBody, taskType);

                    // return result
                    if (resPayload.IsSuccess)
                    {
                        return((TT)resPayload.Data);
                    }
                }

                // throw error
                throw new RpcException(resPayload.Error);
            }
        }