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