/// <summary> /// 请求调用 /// </summary> /// <param name="buffer">已序列化的消息请求</param> /// <returns>序列化消息</returns> public async Task <TProtocol> InvokeAsync(TProtocol buffer) { MessageResponse response = new MessageResponse(); try { Dictionary <string, object> logs = new Dictionary <string, object>(); MessageRequest request = DeserializeMessage(buffer); try { if (request.ClusterToken != _clusterToken) { throw new IllegalClusterTokenException($"Cluster token({request.ClusterToken}) is illegal."); } MethodReflectionInfo methodInfo = EnsureMethodInfo(request); var serviceInstance = _serverStub.GetServiceInstance(request.Service); object result = null; object ret = methodInfo.Method.Invoke(serviceInstance, request.Args?.ToArray()); if (methodInfo.IsAwaitable) //处理异步 { dynamic task = (Task)ret; if (methodInfo.ReturnType.IsGenericType) { result = await task.ConfigureAwait(false); } else { await task.ConfigureAwait(false); } } else { result = ret; } response.MessageId = request.MessageId; response.Data = result; response.ReturnType = result?.GetType()?.AssemblyQualifiedName; response.Success = true; return(SerializeMessage(response)); } catch (Exception ex) { _logger.WriteErrorLog(ex); throw; } finally { } } catch (Exception ex) { response.Message = ex.InnerException != null ? ex.InnerException.Message : ex.Message; _logger.WriteErrorLog(ex); } return(SerializeMessage(response)); }
/// <summary> /// 调用入口 /// </summary> /// <param name="binder">请求的绑定对象</param> /// <param name="args">参数集合</param> /// <param name="result">返回结果</param> /// <returns></returns> public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { //处理参数 MethodReflectionInfo methodInfo = _serviceInfo.EnsureMethodInfo(binder.Name, args, null, binder.CallInfo.ArgumentCount); //序列化消息数据 var request = new MessageRequest { MessageId = Guid.NewGuid().ToString(), Service = _serviceInfo.ServiceType.Name, Method = binder.Name, ClusterToken = _clientStub.ClusterToken, ArgTypes = methodInfo.Parameters.Any() ? new List <string>() : null, Args = methodInfo.Parameters.Any() ? new List <object>() : null }; for (int i = 0; i < methodInfo.Parameters.Length; i++) { request.ArgTypes.Add(methodInfo.Parameters[i].ParameterType.AssemblyQualifiedName); //todo 但继承的子类不在同个程序集的时候无法反射 request.Args.Add(args[i]); } TProtocol message = SerializeMessage(request); MessageResponse response = Invoke(request.MessageId, message, _clientStub.EndPoint); result = response.Data; if (methodInfo.IsAwaitable) //处理异步返回值 { if (methodInfo.ReturnType.IsGenericType) { Type genericParamType = methodInfo.Method.ReturnType.GenericTypeArguments.First(); dynamic value = Utility.ChangeType(result, genericParamType); result = Utility.GetTaskByType(genericParamType, value); } else { result = Task.CompletedTask; } } return(true); }
/// <summary> /// 获取服务方法反射信息 /// </summary> /// <param name="request">请求消息</param> /// <returns>方法反射信息</returns> protected MethodReflectionInfo EnsureMethodInfo(MessageRequest request) { var serviceInfo = _serverStub.GetServiceInfo(request.Service); if (serviceInfo == null) { throw new RpcInternalException($"The service {request.Service} is not found."); } List <Type> types = new List <Type>(); for (int i = 0; i < request.ArgTypes?.Count; i++) { types.Add(Type.GetType(request.ArgTypes[i])); } MethodReflectionInfo methodInfo = serviceInfo.EnsureMethodInfo(request.Method, request.Args?.ToArray(), types.ToArray(), request.Args?.Count ?? 0); if (methodInfo == null) { throw new RpcInternalException($"The parameters of service method {request.Method} is unmatch. Parameters:{(request.ArgTypes == null ? "" : string.Join("; ", request.ArgTypes))}"); } return(methodInfo); }
/// <summary> /// 获取服务信息 /// </summary> /// <param name="type"></param> /// <returns></returns> public static ServiceReflectionInfo GetServiceInfo(Type type) { var info = new ServiceReflectionInfo() { ServiceType = type, Attributes = type.GetCustomAttributes().ToList() }; var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); var methodInfoList = new List <MethodReflectionInfo>(); foreach (var method in methods) { var mInfo = new MethodReflectionInfo() { Attributes = method.GetCustomAttributes().ToList(), Method = method, Parameters = method.GetParameters(), ReturnType = method.ReturnType, IsAwaitable = method.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null }; methodInfoList.Add(mInfo); } info.Methods = methodInfoList; return(info); }