private (Type MessageType, int[] DataIndexes, Type?HeaderType, int[] HeaderIndexes) GetRequestType() { if (Parameters.Length == 0) { return(typeof(Message), Array.Empty <int>(), null, Array.Empty <int>()); } var dataParameters = new List <Type>(); var dataParameterIndexes = new List <int>(); var streamingIndex = -1; for (var i = 0; i < Parameters.Length; i++) { var parameter = Parameters[i]; if (IsDataParameter(parameter.ParameterType)) { if (ReflectionTools.IsAsyncEnumerable(parameter.ParameterType)) { streamingIndex = i; } else { dataParameters.Add(parameter.ParameterType); dataParameterIndexes.Add(i); } } } if (streamingIndex >= 0) { return( MessageBuilder.GetMessageType(Parameters[streamingIndex].ParameterType.GenericTypeArguments[0]), new[] { streamingIndex }, dataParameters.Count > 0 ? MessageBuilder.GetMessageType(dataParameters.ToArray()) : null, dataParameterIndexes.ToArray()); } return( MessageBuilder.GetMessageType(dataParameters.ToArray()), dataParameterIndexes.ToArray(), null, Array.Empty <int>()); }
private MethodType GetOperationType() { var returnType = Operation.ReturnType; if (ReflectionTools.IsTask(returnType)) { var args = returnType.GenericTypeArguments; returnType = args.Length == 0 ? returnType : args[0]; } var responseIsStreaming = ReflectionTools.IsAsyncEnumerable(returnType) || (ReflectionTools.IsValueTuple(returnType) && returnType.GenericTypeArguments.Any(ReflectionTools.IsAsyncEnumerable)); var requestIsStreaming = Parameters.Select(i => i.ParameterType).Any(ReflectionTools.IsAsyncEnumerable); if (responseIsStreaming) { return(requestIsStreaming ? MethodType.DuplexStreaming : MethodType.ServerStreaming); } return(requestIsStreaming ? MethodType.ClientStreaming : MethodType.Unary); }
private void ValidateSignature() { if (Operation.IsGenericMethod) { ThrowInvalidSignature(); } var hasInputStreaming = false; for (var i = 0; i < Parameters.Length; i++) { var parameter = Parameters[i]; if (parameter.IsOut() || parameter.IsRef()) { ThrowInvalidSignature(); } if (IsDataParameter(parameter.ParameterType)) { if (ReflectionTools.IsAsyncEnumerable(parameter.ParameterType)) { if (hasInputStreaming) { ThrowInvalidSignature(); } hasInputStreaming = true; } } else if (!IsContextParameter(parameter.ParameterType)) { ThrowInvalidSignature(); } } }
private (Type ResponseType, int Index, Type?HeaderType, int[] HeaderIndexes) GetResponseType(Type returnType) { if (returnType == typeof(void)) { return(typeof(Message), 0, null, Array.Empty <int>()); } var responseType = returnType; if (ReflectionTools.IsTask(returnType)) { if (!returnType.IsGenericType) { return(typeof(Message), 0, null, Array.Empty <int>()); } responseType = returnType.GenericTypeArguments[0]; } if (ReflectionTools.IsValueTuple(responseType) && responseType.GenericTypeArguments.Any(ReflectionTools.IsAsyncEnumerable)) { if (!ReflectionTools.IsTask(returnType)) { ThrowInvalidSignature("Wrap return type with Task<> or ValueTask<>."); } var genericArguments = responseType.GenericTypeArguments; if (genericArguments.Length == 1) { ThrowInvalidSignature("Unwrap return type from ValueTuple<>."); } var streamIndex = -1; var headerIndexes = new List <int>(); var headerTypes = new List <Type>(); for (var i = 0; i < genericArguments.Length; i++) { var genericArgument = genericArguments[i]; if (ReflectionTools.IsAsyncEnumerable(genericArgument)) { responseType = genericArgument.GenericTypeArguments[0]; if (streamIndex >= 0 || IsContextParameter(responseType) || !IsDataParameter(responseType)) { ThrowInvalidSignature(); } streamIndex = i; } else if (IsContextParameter(genericArgument) || !IsDataParameter(genericArgument)) { ThrowInvalidSignature(); } else { headerIndexes.Add(i); headerTypes.Add(genericArgument); } } return( MessageBuilder.GetMessageType(responseType), streamIndex, MessageBuilder.GetMessageType(headerTypes.ToArray()), headerIndexes.ToArray()); } if (ReflectionTools.IsAsyncEnumerable(responseType)) { responseType = responseType.GenericTypeArguments[0]; } if (IsContextParameter(responseType) || !IsDataParameter(responseType)) { ThrowInvalidSignature(); } return(MessageBuilder.GetMessageType(responseType), 0, null, Array.Empty <int>()); }