internal RpcOperationInfo(string name,
                           RpcServiceInfo service,
                           MemberInfo declaringMember,
                           MethodInfo method,
                           RpcMethodType methodType,
                           bool isAsync,
                           ImmutableArray <RpcRequestParameter> requestParameters,
                           int?callbackParameterIndex,
                           int?cancellationTokenIndex,
                           Type returnType,
                           Type responseReturnType,
                           Type requestType,
                           Type responseType,
                           ServiceOperationReturnKind returnKind,
                           bool allowInlineExecution,
                           ImmutableArray <object> metadata) :
     base(name, service, declaringMember, metadata)
 {
     this.Method                 = method ?? throw new ArgumentNullException(nameof(method));
     this.MethodType             = methodType;
     this.IsAsync                = isAsync;
     this.RequestParameters      = !requestParameters.IsDefault ? requestParameters : throw new ArgumentNullException(nameof(requestParameters));
     this.CallbackParameterIndex = callbackParameterIndex;
     this.CancellationTokenIndex = cancellationTokenIndex;
     this.ReturnType             = returnType ?? throw new ArgumentNullException(nameof(returnType));
     this.ResponseReturnType     = responseReturnType ?? throw new ArgumentNullException(nameof(responseReturnType));
     this.RequestType            = requestType ?? throw new ArgumentNullException(nameof(requestType));
     this.ResponseType           = responseType ?? throw new ArgumentNullException(nameof(responseType));
     this.ReturnKind             = returnKind;
     this.AllowInlineExecution   = allowInlineExecution;
 }
        /// <summary>
        /// Will be called by generated code. A RpcProxyBase implementation class must have a static
        /// method named CreateMethodDef, with this signature.
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="methodType"></param>
        /// <param name="serviceName"></param>
        /// <param name="methodName"></param>
        /// <param name="serializerOverride"></param>
        /// <param name="faultHandler"></param>
        /// <returns></returns>
        public static GrpcProxyMethod CreateMethodDef <TRequest, TResponse>(
            RpcMethodType methodType, string serviceName, string methodName,
            IRpcSerializer?serializerOverride,
            RpcClientFaultHandler?faultHandler)
            where TRequest : class
            where TResponse : class
        {
            GrpcCore.MethodType grpcMethodType;
            switch (methodType)
            {
            case RpcMethodType.ServerStreaming:
                grpcMethodType = GrpcCore.MethodType.ServerStreaming;
                break;

            case RpcMethodType.EventAdd:
                grpcMethodType = GrpcCore.MethodType.ServerStreaming;
                break;

            case RpcMethodType.Unary:
            //case RpcMethodType.PropertyGet:
            //case RpcMethodType.PropertySet:
            case RpcMethodType.EventRemove:
                grpcMethodType = GrpcCore.MethodType.Unary;
                break;

            default:
                throw new ArgumentException($"Unknown methodType 'methodType'", nameof(methodType));
            }

            return(new GrpcProxyMethod <TRequest, TResponse>(grpcMethodType, serviceName, methodName, serializerOverride, faultHandler));
        }
Beispiel #3
0
 // TODO: This should be be moved to a virtual method in RpcServiceProxyBuilder returning an Expression.
 public static LightweightMethodDef CreateMethodDef <TRequest, TResponse>(
     RpcMethodType methodType,
     string serviceName, string methodName,
     IRpcSerializer?serializer,
     RpcClientFaultHandler?faultHandler)
 {
     return(new LightweightMethodDef <TRequest, TResponse>(methodType, $"{serviceName}.{methodName}", serializer, faultHandler));
 }
 public EthRpcMethod(string method, RpcMethodType rpcMethodType, RpcCacheStrategy rpcCacheStrategy, int cacheOption, ParamToString paramDelegate = null, CacheFilter filter = null)
 {
     Method           = method;
     RpcMethodType    = rpcMethodType;
     RpcCacheStrategy = rpcCacheStrategy;
     CacheOption      = cacheOption;
     ParamDelegate    = paramDelegate;
     FilterDelegate   = filter;
 }
 protected LightweightMethodDef(
     RpcMethodType methodType,
     string operationName,
     IRpcSerializer?serializerOverride,
     RpcClientFaultHandler?faultHandler)
     : base(serializerOverride, faultHandler)
 {
     this.MethodType    = methodType;
     this.OperationName = operationName;
 }
        private static Type GetResponseType(RpcMethodType methodType, Type responseReturnType)
        {
            if (methodType == RpcMethodType.ServerStreaming)
            {
                return(responseReturnType);
            }

            if (typeof(void).Equals(responseReturnType))
            {
                return(typeof(RpcResponse));
            }

            return(typeof(RpcResponse <>).MakeGenericType(responseReturnType));
        }
 public EthRpcMethod(string method, RpcMethodType rpcMethodType, RpcCacheStrategy rpcCacheStrategy)
 {
     Method           = method;
     RpcMethodType    = rpcMethodType;
     RpcCacheStrategy = rpcCacheStrategy;
 }
        public static RpcOperationInfo GetOperationInfoFromMethod(RpcServiceInfo serviceInfo, MethodInfo method)
        {
            var parameters = method.GetParameters();

            var requestTypeInfo = GetRequestType(parameters, serviceInfo.IsSingleton);

            Type          actualReturnType = method.ReturnType;
            bool          isAsync          = false;
            RpcMethodType methodType       = RpcMethodType.Unary;

            if (method.ReturnType.IsGenericType)
            {
                var genericTypeDef = method.ReturnType.GetGenericTypeDefinition();
                if (genericTypeDef.Equals(typeof(IAsyncEnumerable <>)))// || genericTypeDef.Equals(typeof(IAsyncEnumerator<>)))
                {
                    if (requestTypeInfo.CallbackParameterIndex != null)
                    {
                        throw new RpcDefinitionException($"A streaming server method '{method.Name}' cannot have a callback parameter.");
                    }
                    actualReturnType = method.ReturnType.GenericTypeArguments[0];
                    methodType       = RpcMethodType.ServerStreaming;
                    isAsync          = true;
                }
                else if (genericTypeDef.Equals(typeof(Task <>)) || genericTypeDef.Equals(typeof(ValueTask <>)))
                {
                    actualReturnType = method.ReturnType.GenericTypeArguments[0];
                    isAsync          = true;
                }
            }
            else if (method.ReturnType == typeof(Task))
            {
                actualReturnType = typeof(void);
                isAsync          = true;
            }
            else
            {
                actualReturnType = method.ReturnType;
            }

            if (requestTypeInfo.CallbackParameterIndex != null)
            {
                if (!typeof(void).Equals(actualReturnType))
                {
                    throw new RpcDefinitionException($"Method '{method.Name}' has a callback parameter and must return void.");
                }

                actualReturnType = requestTypeInfo.CallbackRequestType ?? throw new InvalidOperationException("CallbackRequestType must be initialized when CallbackParameterIndex is not null");
                methodType       = RpcMethodType.ServerStreaming;
            }

            string?operationName = null;

            var rpcAttribute = method.GetCustomAttribute <RpcOperationAttribute>();

            if (rpcAttribute != null)
            {
                operationName = rpcAttribute.Name;
            }

            if (string.IsNullOrEmpty(operationName))
            {
                operationName = method.Name;
                if (isAsync && operationName.EndsWith("Async", StringComparison.Ordinal))
                {
                    operationName = operationName.Substring(0, operationName.Length - "Async".Length);
                }
            }

            var(returnKind, responseReturnType) = GetOperationReturnKind(actualReturnType);
            Type responseType = GetResponseType(methodType, responseReturnType);

            ImmutableArray <object> metadata = GetMethodMetadata(serviceInfo, method);

            return(new RpcOperationInfo
                   (
                       service: serviceInfo,
                       method: method,
                       declaringMember: method,
                       methodType: methodType,
                       isAsync: isAsync,
                       name: operationName !,
                       requestParameters: requestTypeInfo.Parameters,
                       callbackParameterIndex: requestTypeInfo.CallbackParameterIndex,
                       cancellationTokenIndex: requestTypeInfo.CancellationTokenIndex,
                       requestType: requestTypeInfo.Type,
                       returnType: actualReturnType,
                       responseType: responseType,
                       responseReturnType: responseReturnType,
                       returnKind: returnKind,
                       allowInlineExecution: rpcAttribute?.AllowInlineExecution ?? false,
                       metadata: metadata
                   ));
        }