private IMessage HandleRequestWithParameters(IMethodCallMessage methodCall, ParsedMethodInfo pmi)
        {
            var deliveredArguments = new string[methodCall.InArgCount];

            for (var i = 0; i < deliveredArguments.Length; ++i)
            {
                deliveredArguments[i] = methodCall.GetArgName(i);
            }

            var arguments = new object[pmi.ArgumentsOrder.Length];

            for (var i = 0; i < arguments.Length; ++i)
            {
                var arg   = pmi.ArgumentsOrder[i];
                var index = Array.FindIndex(deliveredArguments, expectedArgPosition => expectedArgPosition == arg);
                if (index >= 0)
                {
                    arguments[i] = methodCall.GetInArg(index);
                }
                else
                {
                    arguments[i] = null;
                }
            }

            Action <object> callback = FindCallbackMethod(methodCall, pmi.CallbackArgumentName);

            if (callback == null)
            {
                throw new SystemException("No callback reference found!");
            }
            var fullRequest = string.Format(pmi.RequestUrl, arguments);

            _context.StartCoroutine(DownloadDataCoroutine(callback, pmi.ReturnType, fullRequest));

            return(new ReturnMessage(null, null, 0, methodCall.LogicalCallContext, methodCall));
        }
        private void ParseMethodInfo(MethodInfo methodInfo)
        {
            var getRequestAttribute = methodInfo.GetCustomAttribute(typeof(GetRequestAttribute)) as GetRequestAttribute;

            if (getRequestAttribute == null)
            {
                throw new SystemException(string.Format("Method {0} is unsupported", methodInfo.Name));
            }

            if (getRequestAttribute.RequestUrl == null)
            {
                throw new SystemException("Request url is missing");
            }

            var parsedMethodInfo = new ParsedMethodInfo()
            {
                RequestUrl           = getRequestAttribute.RequestUrl,
                ArgumentsOrder       = getRequestAttribute.ParamNames,
                CallbackArgumentName = getRequestAttribute.CallbackArgumentName,
                ReturnType           = getRequestAttribute.AnswerType
            };

            _parsedMethodInfos.Add(methodInfo.Name, parsedMethodInfo);
        }
        private IMessage HandleRequestWithoutParameters(IMethodCallMessage methodCall, ParsedMethodInfo pmi)
        {
            var fullRequest = pmi.RequestUrl;
            var callback    = FindCallbackMethod(methodCall, pmi.CallbackArgumentName);

            if (callback == null)
            {
                throw new SystemException("No callback reference found!");
            }
            _context.StartCoroutine(DownloadDataCoroutine(callback, pmi.ReturnType, fullRequest));

            return(new ReturnMessage(null, null, 0, methodCall.LogicalCallContext, methodCall));
        }
        private MethodInfo Deserialize(ParsedMethodInfo parsedMethodInfo, Type reflectedType)
        {
            if (parsedMethodInfo == null)
            {
                throw new ArgumentNullException(nameof(parsedMethodInfo));
            }
            if (reflectedType == null)
            {
                throw new ArgumentNullException(nameof(reflectedType));
            }

            BindingFlags bindingFlags = (parsedMethodInfo.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) |
                                        (parsedMethodInfo.IsStatic ? BindingFlags.Static : BindingFlags.Instance);

            Func <IEnumerable <ParameterInfo>, IEnumerable <ParsedParameterInfo>, bool> parametersMatch = (paramterInfos, parsedParameterInfos) =>
            {
                if (paramterInfos == null)
                {
                    throw new ArgumentNullException(nameof(paramterInfos));
                }
                if (parsedParameterInfos == null)
                {
                    throw new ArgumentNullException(nameof(parsedParameterInfos));
                }

                if (paramterInfos.Count() != parsedParameterInfos.Count())
                {
                    return(false);
                }

                for (int i = 0; i < paramterInfos.Count(); i++)
                {
                    ParameterInfo       parameterInfo       = paramterInfos.ElementAt(i);
                    ParsedParameterInfo parsedParameterInfo = parsedParameterInfos.ElementAt(i);

                    if (parameterInfo.Name != parsedParameterInfo.Name)
                    {
                        return(false);
                    }

                    Type source = parsedParameterInfo.ParameterType == null ? null : Deserialize(parsedParameterInfo.ParameterType);
                    if (parameterInfo.ParameterType != source)
                    {
                        Type parameterInfo2 = parameterInfo.ParameterType.IsGenericType ? parameterInfo.ParameterType.GetGenericTypeDefinition() : parameterInfo.ParameterType;
                        Type source2        = source.IsGenericType ? source.GetGenericTypeDefinition() : source;

                        if (parameterInfo2 != source2)
                        {
                            return(false);
                        }
                    }
                }

                return(true);
            };
            Func <IEnumerable <Type>, IEnumerable <ParsedType>, bool> genericArgumentsMatch = (types, parsedTypes) =>
            {
                if (types == null)
                {
                    throw new ArgumentNullException(nameof(types));
                }
                if (parsedTypes == null)
                {
                    throw new ArgumentNullException(nameof(parsedTypes));
                }

                if (types.Count() != parsedTypes.Count())
                {
                    return(false);
                }

                return(true);
            };

            MethodInfo methodInfo = reflectedType.GetMethods(bindingFlags)
                                    .Where(_ => _.Name == parsedMethodInfo.Name &&
                                           _.ReturnType == (parsedMethodInfo.ReturnType == null ? null : Deserialize(parsedMethodInfo.ReturnType)) &&
                                           parametersMatch(_.GetParameters(), parsedMethodInfo.Parameters) &&
                                           genericArgumentsMatch(_.GetGenericArguments(), parsedMethodInfo.GenericArguments))
                                    .SingleOrDefault();

            if (methodInfo != null && methodInfo.GetGenericArguments().Length > 0)
            {
                methodInfo = methodInfo.MakeGenericMethod(parsedMethodInfo.GenericArguments.Select(Deserialize).ToArray());
            }

            return(methodInfo);
        }