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 (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>()); }
public void IsValueTuple(Type type, bool expected) { ReflectionTools.IsValueTuple(type).ShouldBe(expected); }