Exemple #1
0
        public void GetMatchingMethod_ListParam_Match_Snake_Case(string parameterNameCase)
        {
            DefaultRequestMatcher matcher = this.GetMatcher();

            IEnumerable <KeyValuePair <string, RpcParameterType> > parameters = new[]
            {
                new KeyValuePair <string, RpcParameterType>(parameterNameCase, RpcParameterType.String)
            };

            string        methodName       = nameof(MethodMatcherController.SnakeCaseParams);
            var           requestSignature = RpcRequestSignature.Create(methodName, parameters);
            RpcMethodInfo methodInfo       = matcher.GetMatchingMethod(requestSignature);


            Assert.NotNull(methodInfo);
            MethodInfo expectedMethodInfo = typeof(MethodMatcherController).GetMethod(methodName) !;

            Assert.Equal(expectedMethodInfo, methodInfo.MethodInfo);
            Assert.Single(methodInfo.Parameters);

            Assert.False(methodInfo.Parameters[0].IsOptional);
            Assert.Equal(typeof(string), methodInfo.Parameters[0].RawType);
            Assert.Equal(RpcParameterType.String, methodInfo.Parameters[0].Type);
            Assert.True(RpcUtil.NamesMatch(methodInfo.Parameters[0].Name, parameterNameCase));
        }
        private IRpcMethodInfo[] FilterMatchesByCaseSensitiveMethod(RpcRequestSignature requestSignature, Span <IRpcMethodInfo> matches)
        {
            //Try to remove ambiguity with case sensitive check
            IRpcMethodInfo[] caseSensitiveMatches = ArrayPool <IRpcMethodInfo> .Shared.Rent(matches.Length);

            try
            {
                int caseSensitiveCount = 0;
                for (int i = 0; i < matches.Length; i++)
                {
                    IRpcMethodInfo m = matches[i];
                    Memory <char>  requestMethodName = requestSignature.GetMethodName();
                    if (m.Name.Length == requestMethodName.Length)
                    {
                        if (!RpcUtil.NamesMatch(m.Name.AsSpan(), requestMethodName.Span))
                        {
                            //TODO do we care about the case where 2+ parameters have very similar names and types?
                            continue;
                        }
                        caseSensitiveMatches[caseSensitiveCount++] = m;
                    }
                }
                return(caseSensitiveMatches.AsSpan(0, caseSensitiveCount).ToArray());
            }
            finally
            {
                ArrayPool <IRpcMethodInfo> .Shared.Return(caseSensitiveMatches, clearArray : false);
            }
        }
        private IRpcMethodInfo[] FilterBySimilarParams(RpcRequestSignature requestSignature, Span <IRpcMethodInfo> methodsWithSameName)
        {
            IRpcMethodInfo[] potentialMatches = ArrayPool <IRpcMethodInfo> .Shared.Rent(methodsWithSameName.Length);

            try
            {
                int potentialMatchCount = 0;
                for (int i = 0; i < methodsWithSameName.Length; i++)
                {
                    IRpcMethodInfo m = methodsWithSameName[i];

                    bool isMatch = this.ParametersMatch(requestSignature, m.Parameters);
                    if (isMatch)
                    {
                        potentialMatches[potentialMatchCount++] = m;
                    }
                }

                if (potentialMatchCount <= 1)
                {
                    return(potentialMatches.AsSpan(0, potentialMatchCount).ToArray());
                }
                return(this.FilterMatchesByCaseSensitiveMethod(requestSignature, potentialMatches.AsSpan(0, potentialMatchCount)));
            }
            finally
            {
                ArrayPool <IRpcMethodInfo> .Shared.Return(potentialMatches, clearArray : false);
            }
        }
        private IRpcMethodInfo[] GetMatchingMethods(RpcRequestSignature requestSignature, IReadOnlyList <IRpcMethodInfo> methods)
        {
            IRpcMethodInfo[] methodsWithSameName = ArrayPool <IRpcMethodInfo> .Shared.Rent(methods.Count);

            try
            {
                //Case insenstive check for hybrid approach. Will check for case sensitive if there is ambiguity
                int methodsWithSameNameCount = 0;
                for (int i = 0; i < methods.Count; i++)
                {
                    IRpcMethodInfo methodInfo = methods[i];
                    if (RpcUtil.NamesMatch(methodInfo.Name.AsSpan(), requestSignature.GetMethodName().Span))
                    {
                        methodsWithSameName[methodsWithSameNameCount++] = methodInfo;
                    }
                }

                if (methodsWithSameNameCount < 1)
                {
                    return(Array.Empty <IRpcMethodInfo>());
                }
                return(this.FilterBySimilarParams(requestSignature, methodsWithSameName.AsSpan(0, methodsWithSameNameCount)));
            }
            finally
            {
                ArrayPool <IRpcMethodInfo> .Shared.Return(methodsWithSameName, clearArray : false);
            }
        }
        public RpcMethodInfo GetMatchingMethod(RpcRequestSignature requestSignature)
        {
            this.logger.AttemptingToMatchMethod(new string(requestSignature.GetMethodName().Span));

            IReadOnlyList <MethodInfo> methods = this.methodProvider.Get();

            if (methods == null || !methods.Any())
            {
                throw new RpcException(RpcErrorCode.MethodNotFound, $"No methods found for route");
            }

            RpcMethodInfo[] compiledMethods = ArrayPool <RpcMethodInfo> .Shared.Rent(methods.Count);

            Span <RpcMethodInfo> matches;

            try
            {
                this.FillRpcMethodInfos(methods, compiledMethods);
                matches = this.FilterAndBuildMethodInfoByRequest(compiledMethods.AsMemory(0, methods.Count), requestSignature);
            }
            finally
            {
                ArrayPool <RpcMethodInfo> .Shared.Return(compiledMethods, clearArray : true);
            }
            if (matches.Length == 1)
            {
                this.logger.RequestMatchedMethod();
                return(matches[0]);
            }

            string errorMessage;

            if (matches.Length > 1)
            {
                var methodInfoList = new List <string>();
                foreach (RpcMethodInfo matchedMethod in matches)
                {
                    var parameterTypeList = new List <string>();
                    foreach (ParameterInfo parameterInfo in matchedMethod.MethodInfo.GetParameters())
                    {
                        string parameterType = parameterInfo.Name + ": " + parameterInfo.ParameterType.Name;
                        if (parameterInfo.IsOptional)
                        {
                            parameterType += "(Optional)";
                        }
                        parameterTypeList.Add(parameterType);
                    }
                    string parameterString = string.Join(", ", parameterTypeList);
                    methodInfoList.Add($"{{Name: '{matchedMethod.MethodInfo.Name}', Parameters: [{parameterString}]}}");
                }
                errorMessage = "More than one method matched the rpc request. Unable to invoke due to ambiguity. Methods that matched the same name: " + string.Join(", ", methodInfoList);
            }
            else
            {
                //Log diagnostics
                this.logger.MethodsInRoute(methods);
                errorMessage = "No methods matched request.";
            }
            throw new RpcException(RpcErrorCode.MethodNotFound, errorMessage);
        }
Exemple #6
0
        public void Create_NullDictParam_Valid()
        {
            string methodName = "Test";
            var    signature  = RpcRequestSignature.Create(methodName, parameters: (IEnumerable <KeyValuePair <string, RpcParameterType> >?)null);

            Assert.Equal(methodName, signature.GetMethodName().ToString());
            Assert.False(signature.HasParameters);
            Assert.False(signature.IsDictionary);
            Assert.Empty(signature.ParametersAsList);
        }
Exemple #7
0
        public void SimpleIterationSetup()
        {
            var parameters = new Dictionary <string, RpcParameterType>
            {
                { "a", RpcParameterType.Number },
                { "b", RpcParameterType.Boolean },
                { "c", RpcParameterType.String }
            };

            this.requestsignature = RpcRequestSignature.Create(nameof(MethodClass.SimpleParamsNoReturn), parameters);
        }
Exemple #8
0
        public void Create_EmptyDictParam_Valid()
        {
            string methodName = "Test";
            var    parameters = new Dictionary <string, RpcParameterType>();
            var    signature  = RpcRequestSignature.Create(methodName, parameters);

            Assert.Equal(methodName, signature.GetMethodName().ToString());
            Assert.False(signature.HasParameters);
            Assert.True(signature.IsDictionary);
            this.AssertDictsEqual(parameters, signature.ParametersAsDict);
        }
Exemple #9
0
        public void Create_MultiListParam_Valid()
        {
            string methodName = "Test";

            RpcParameterType[] parameters = new[] { RpcParameterType.String, RpcParameterType.Boolean, RpcParameterType.Null, RpcParameterType.Number, RpcParameterType.Object };
            var signature = RpcRequestSignature.Create(methodName, parameters);

            Assert.Equal(methodName, signature.GetMethodName().ToString());
            Assert.True(signature.HasParameters);
            Assert.False(signature.IsDictionary);
            Assert.Equal(parameters, signature.ParametersAsList);
        }
Exemple #10
0
        public void Create_EmptyListParam_Valid()
        {
            string methodName = "Test";

            RpcParameterType[] parameters = new RpcParameterType[0];
            var signature = RpcRequestSignature.Create(methodName, parameters);

            Assert.Equal(methodName, signature.GetMethodName().ToString());
            Assert.False(signature.HasParameters);
            Assert.False(signature.IsDictionary);
            Assert.Equal(parameters, signature.ParametersAsList);
        }
        public IRpcMethodInfo GetMatchingMethod(RpcRequestSignature requestSignature)
        {
            this.logger.AttemptingToMatchMethod(new string(requestSignature.GetMethodName().Span));

            RpcContext context = this.contextAccessor.Get();
            IReadOnlyList <IRpcMethodInfo>?methods = this.methodProvider.GetByPath(context.Path);

            if (methods == null || !methods.Any())
            {
                throw new RpcException(RpcErrorCode.MethodNotFound, $"No methods found for route");
            }

            Span <IRpcMethodInfo> matches = this.FilterAndBuildMethodInfoByRequest(methods, requestSignature);

            if (matches.Length == 1)
            {
                this.logger.RequestMatchedMethod();
                return(matches[0]);
            }

            string errorMessage;

            if (matches.Length > 1)
            {
                var methodInfoList = new List <string>();
                foreach (IRpcMethodInfo matchedMethod in matches)
                {
                    var parameterTypeList = new List <string>();
                    foreach (IRpcParameterInfo parameterInfo in matchedMethod.Parameters)
                    {
                        string parameterType = parameterInfo.Name + ": " + parameterInfo.Type;
                        if (parameterInfo.IsOptional)
                        {
                            parameterType += "(Optional)";
                        }
                        parameterTypeList.Add(parameterType);
                    }
                    string parameterString = string.Join(", ", parameterTypeList);
                    methodInfoList.Add($"{{Name: '{matchedMethod.Name}', Parameters: [{parameterString}]}}");
                }
                errorMessage = "More than one method matched the rpc request. Unable to invoke due to ambiguity. Methods that matched the same name: " + string.Join(", ", methodInfoList);
            }
            else
            {
                //Log diagnostics
                this.logger.MethodsInRoute(methods);
                errorMessage = "No methods matched request.";
            }
            throw new RpcException(RpcErrorCode.MethodNotFound, errorMessage);
        }
Exemple #12
0
        public void GetMatchingMethod_SimpleMulitParam_DictMatch()
        {
            DefaultRequestMatcher matcher = this.GetMatcher();

            var parameters = new Dictionary <string, RpcParameterType>
            {
                { "a", RpcParameterType.Number },
                { "b", RpcParameterType.Boolean },
                { "c", RpcParameterType.String },
                { "d", RpcParameterType.Object },
                { "e", RpcParameterType.Null }
            };
            string        methodName       = nameof(MethodMatcherController.SimpleMulitParam);
            var           requestSignature = RpcRequestSignature.Create(methodName, parameters);
            RpcMethodInfo methodInfo       = matcher.GetMatchingMethod(requestSignature);


            Assert.NotNull(methodInfo);
            MethodInfo expectedMethodInfo = typeof(MethodMatcherController).GetMethod(methodName) !;

            Assert.Equal(expectedMethodInfo, methodInfo.MethodInfo);
            Assert.Equal(5, methodInfo.Parameters.Length);

            Assert.False(methodInfo.Parameters[0].IsOptional);
            Assert.Equal(typeof(int), methodInfo.Parameters[0].RawType);
            Assert.Equal(RpcParameterType.Number, methodInfo.Parameters[0].Type);
            Assert.Equal("a", methodInfo.Parameters[0].Name);

            Assert.False(methodInfo.Parameters[1].IsOptional);
            Assert.Equal(typeof(bool), methodInfo.Parameters[1].RawType);
            Assert.Equal(RpcParameterType.Boolean, methodInfo.Parameters[1].Type);
            Assert.Equal("b", methodInfo.Parameters[1].Name);

            Assert.False(methodInfo.Parameters[2].IsOptional);
            Assert.Equal(typeof(string), methodInfo.Parameters[2].RawType);
            Assert.Equal(RpcParameterType.String, methodInfo.Parameters[2].Type);
            Assert.Equal("c", methodInfo.Parameters[2].Name);

            Assert.False(methodInfo.Parameters[3].IsOptional);
            Assert.Equal(typeof(object), methodInfo.Parameters[3].RawType);
            Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[3].Type);
            Assert.Equal("d", methodInfo.Parameters[3].Name);

            Assert.True(methodInfo.Parameters[4].IsOptional);
            Assert.Equal(typeof(int?), methodInfo.Parameters[4].RawType);
            Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[4].Type);
            Assert.Equal("e", methodInfo.Parameters[4].Name);
        }
Exemple #13
0
        public void GetMatchingMethod_GuidParameter_Match()
        {
            string methodName = nameof(MethodMatcherController.GuidTypeMethod);

            DefaultRequestMatcher matcher   = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name);
            var            requestSignature = RpcRequestSignature.Create(methodName, new[] { RpcParameterType.String });
            IRpcMethodInfo methodInfo       = matcher.GetMatchingMethod(requestSignature);

            Assert.NotNull(methodInfo);
            Assert.Equal(methodName, methodInfo.Name);
            Assert.Single(methodInfo.Parameters);
            Assert.False(methodInfo.Parameters[0].IsOptional);
            Assert.Equal(typeof(Guid), methodInfo.Parameters[0].RawType);
            Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[0].Type);
            Assert.Equal("guid", methodInfo.Parameters[0].Name);
        }
Exemple #14
0
        public void GetMatchingMethod_WithRpcRoute()
        {
            string methodName = nameof(MethodMatcherController.GuidTypeMethod);
            RpcRequestSignature requestSignature = RpcRequestSignature.Create(methodName, new[] { RpcParameterType.String });

            DefaultRequestMatcher path1Matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name);
            IRpcMethodInfo        path1Match   = path1Matcher.GetMatchingMethod(requestSignature);

            Assert.NotNull(path1Match);


            DefaultRequestMatcher path2Matcher = this.GetMatcher(path: typeof(MethodMatcherDuplicatesController).GetTypeInfo().Name);
            IRpcMethodInfo        path2Match   = path2Matcher.GetMatchingMethod(requestSignature);

            Assert.NotNull(path2Match);
            Assert.NotSame(path1Match, path2Match);
        }
Exemple #15
0
        public void Create_MultiDictParam_Valid()
        {
            string methodName = "Test";
            var    parameters = new Dictionary <string, RpcParameterType>
            {
                ["String"]  = RpcParameterType.String,
                ["Boolean"] = RpcParameterType.Boolean,
                ["Null"]    = RpcParameterType.Null,
                ["Number"]  = RpcParameterType.Number,
                ["Object"]  = RpcParameterType.Object,
            };
            var signature = RpcRequestSignature.Create(methodName, parameters);

            Assert.Equal(methodName, signature.GetMethodName().ToString());
            Assert.True(signature.HasParameters);
            Assert.True(signature.IsDictionary);
            this.AssertDictsEqual(parameters, signature.ParametersAsDict);
        }
Exemple #16
0
        public void GetMatchingMethod_ListParam_Match()
        {
            DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name);

            RpcParameterType[] parameters   = new[] { RpcParameterType.Object };
            string             methodName   = nameof(MethodMatcherController.List);
            var            requestSignature = RpcRequestSignature.Create(methodName, parameters);
            IRpcMethodInfo methodInfo       = matcher.GetMatchingMethod(requestSignature);


            Assert.NotNull(methodInfo);
            Assert.Equal(methodName, methodInfo.Name);
            Assert.Single(methodInfo.Parameters);

            Assert.False(methodInfo.Parameters[0].IsOptional);
            Assert.Equal(typeof(List <string>), methodInfo.Parameters[0].RawType);
            Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[0].Type);
            Assert.Equal("values", methodInfo.Parameters[0].Name);
        }
Exemple #17
0
        public void GetMatchingMethod_CulturallyInvariantComparison()
        {
            DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name);

            RpcParameterType[] parameters = Array.Empty <RpcParameterType>();
            string             methodName = nameof(MethodMatcherController.IsLunchTime);
            // Use lowercase version of method name when making request.
            var methodNameLower  = methodName.ToLowerInvariant();
            var requestSignature = RpcRequestSignature.Create(methodNameLower, parameters);
            var previousCulture  = System.Globalization.CultureInfo.CurrentCulture;

            // Switch to a culture that would result in lowercasing 'I' to
            // U+0131, if not done with invariant culture.
            System.Globalization.CultureInfo.CurrentCulture = new System.Globalization.CultureInfo("az");
            IRpcMethodInfo methodInfo = matcher.GetMatchingMethod(requestSignature);

            Assert.NotNull(methodInfo);
            Assert.Equal(methodName, methodInfo.Name);
            System.Globalization.CultureInfo.CurrentCulture = previousCulture;
        }
Exemple #18
0
        public void GetMatchingMethod_SimpleMulitParam_ListMatch()
        {
            DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name);

            RpcParameterType[] parameters   = new[] { RpcParameterType.Number, RpcParameterType.Boolean, RpcParameterType.String, RpcParameterType.Object, RpcParameterType.Null };
            string             methodName   = nameof(MethodMatcherController.SimpleMulitParam);
            var            requestSignature = RpcRequestSignature.Create(methodName, parameters);
            IRpcMethodInfo methodInfo       = matcher.GetMatchingMethod(requestSignature);


            Assert.NotNull(methodInfo);
            Assert.Equal(methodName, methodInfo.Name);
            Assert.Equal(5, methodInfo.Parameters.Count);

            Assert.False(methodInfo.Parameters[0].IsOptional);
            Assert.Equal(typeof(int), methodInfo.Parameters[0].RawType);
            Assert.Equal(RpcParameterType.Number, methodInfo.Parameters[0].Type);
            Assert.Equal("a", methodInfo.Parameters[0].Name);

            Assert.False(methodInfo.Parameters[1].IsOptional);
            Assert.Equal(typeof(bool), methodInfo.Parameters[1].RawType);
            Assert.Equal(RpcParameterType.Boolean, methodInfo.Parameters[1].Type);
            Assert.Equal("b", methodInfo.Parameters[1].Name);

            Assert.False(methodInfo.Parameters[2].IsOptional);
            Assert.Equal(typeof(string), methodInfo.Parameters[2].RawType);
            Assert.Equal(RpcParameterType.String, methodInfo.Parameters[2].Type);
            Assert.Equal("c", methodInfo.Parameters[2].Name);

            Assert.False(methodInfo.Parameters[3].IsOptional);
            Assert.Equal(typeof(object), methodInfo.Parameters[3].RawType);
            Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[3].Type);
            Assert.Equal("d", methodInfo.Parameters[3].Name);

            Assert.True(methodInfo.Parameters[4].IsOptional);
            Assert.Equal(typeof(int?), methodInfo.Parameters[4].RawType);
            Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[4].Type);
            Assert.Equal("e", methodInfo.Parameters[4].Name);
        }
Exemple #19
0
 public void ComplexIterationSetup()
 {
     this.requestsignature = RpcRequestSignature.Create(nameof(MethodClass.ComplexParamNoReturn), new[] { RpcParameterType.Object });
 }
Exemple #20
0
 public void IterationSetup()
 {
     this.requestsignature = RpcRequestSignature.Create(nameof(MethodClass.NoParamsNoReturn));
 }
Exemple #21
0
        /// <summary>
        /// Call the incoming Rpc request method and gives the appropriate response
        /// </summary>
        /// <param name="request">Rpc request</param>
        /// <param name="path">Rpc path that applies to the current request</param>
        /// <param name="routeContext">The context of the current rpc request</param>
        /// <returns>An Rpc response for the request</returns>
        public async Task <RpcResponse?> InvokeRequestAsync(RpcRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            this.logger.InvokingRequest(request.Id);
            RpcResponse rpcResponse;

            try
            {
                RpcMethodInfo rpcMethod;
                using (var requestSignature = RpcRequestSignature.Create(request))
                {
                    rpcMethod = this.rpcRequestMatcher.GetMatchingMethod(requestSignature);
                }

                bool isAuthorized = await this.authorizationHandler.IsAuthorizedAsync(rpcMethod.MethodInfo);

                if (isAuthorized)
                {
                    object[] realParameters = this.ParseParameters(request.Parameters, rpcMethod.Parameters);

                    this.logger.InvokeMethod(request.Method);
                    IRpcContext routeContext = this.contextAccessor.Value !;
                    object?     result       = await this.InvokeAsync(rpcMethod.MethodInfo, realParameters, request, routeContext.RequestServices);

                    this.logger.InvokeMethodComplete(request.Method);

                    if (result is IRpcMethodResult methodResult)
                    {
                        rpcResponse = methodResult.ToRpcResponse(request.Id);
                    }
                    else
                    {
                        rpcResponse = new RpcResponse(request.Id, result);
                    }
                }
                else
                {
                    var authError = new RpcError(RpcErrorCode.InvalidRequest, "Unauthorized");
                    rpcResponse = new RpcResponse(request.Id, authError);
                }
            }
            catch (Exception ex)
            {
                const string errorMessage = "An Rpc error occurred while trying to invoke request.";
                this.logger.LogException(ex, errorMessage);
                RpcError error;
                if (ex is RpcException rpcException)
                {
                    error = rpcException.ToRpcError(this.serverConfig.Value.ShowServerExceptions);
                }
                else
                {
                    error = new RpcError(RpcErrorCode.InternalError, errorMessage, ex);
                }
                rpcResponse = new RpcResponse(request.Id, error);
            }

            if (request.Id.HasValue)
            {
                this.logger.FinishedRequest(request.Id.ToString());
                //Only give a response if there is an id
                return(rpcResponse);
            }
            //TODO make no id run in a non-blocking way
            this.logger.FinishedRequestNoId();
            return(null);
        }
        private bool ParametersMatch(RpcRequestSignature requestSignature, IReadOnlyList <IRpcParameterInfo> parameters)
        {
            if (!requestSignature.HasParameters)
            {
                return(parameters == null || !parameters.Any(p => !p.IsOptional));
            }
            int parameterCount = 0;

            if (requestSignature.IsDictionary)
            {
                foreach ((Memory <char> name, RpcParameterType type) in requestSignature.ParametersAsDict)
                {
                    bool found = false;
                    for (int paramIndex = 0; paramIndex < parameters.Count; paramIndex++)
                    {
                        IRpcParameterInfo parameter = parameters[paramIndex];
                        if (!RpcUtil.NamesMatch(parameter.Name.AsSpan(), name.Span) ||
                            !RpcParameterUtil.TypesCompatible(parameter.Type, type))
                        {
                            continue;
                        }
                        found = true;
                        break;
                    }
                    if (!found)
                    {
                        return(false);
                    }
                    parameterCount++;
                }
            }
            else
            {
                foreach (RpcParameterType parameterType in requestSignature.ParametersAsList)
                {
                    if (parameters.Count <= parameterCount)
                    {
                        return(false);
                    }
                    IRpcParameterInfo info = parameters[parameterCount];
                    if (!RpcParameterUtil.TypesCompatible(info.Type, parameterType))
                    {
                        return(false);
                    }

                    parameterCount++;
                }


                for (int i = parameterCount; i < parameters.Count; i++)
                {
                    //Only if the last parameters in the method are optional does the request match
                    //Will be skipped if they are equal length
                    if (!parameters[i].IsOptional)
                    {
                        return(false);
                    }
                }
            }
            if (parameterCount != parameters.Count)
            {
                return(false);
            }
            return(true);
        }
        private IRpcMethodInfo[] FilterAndBuildMethodInfoByRequest(IReadOnlyList <IRpcMethodInfo> methods, RpcRequestSignature requestSignature)
        {
            //If the request signature is found, it means we have the methods cached already

            var rpcPath             = this.contextAccessor.Get()?.Path;
            var rpcPathMethodsCache = DefaultRequestMatcher.requestToMethodCache.GetOrAdd(rpcPath, path => new ConcurrentDictionary <RpcRequestSignature, IRpcMethodInfo[]>());

            return(rpcPathMethodsCache.GetOrAdd(requestSignature, BuildMethodCache));

            IRpcMethodInfo[] BuildMethodCache(RpcRequestSignature s)
            {
                return(this.GetMatchingMethods(s, methods));
            }
        }