/// <summary>
        /// Creates an IPC request for the given method in the given interface. Does not support generic methods.
        /// </summary>
        /// <param name="interfaceType">The Type of the interface containing the method.</param>
        /// <param name="methodName">Name of the method.</param>
        /// <param name="args">The arguments to the method.</param>
        /// <returns>IpcRequest object</returns>
        public static IpcRequest CreateIpcRequest(Type interfaceType, string methodName, bool useIpcRequestParameterType, params object[] args)
        {
            MethodInfo method = null;

            // Try to find the matching method based on name and args
            if (args.All(x => x != null))
            {
                method = interfaceType.GetMethod(methodName, args.Select(x => x.GetType()).ToArray());
            }

            if (method == null)
            {
                method = interfaceType.GetMethod(methodName);
            }

            if (method == null)
            {
                throw new ArgumentException($"Could not find a valid method in {interfaceType}!");
            }

            if (method.IsGenericMethod)
            {
                throw new ArgumentException("Generic methods are not supported!", nameof(methodName));
            }

            var methodParams = method.GetParameters();

            var request = new IpcRequest()
            {
                MethodName = methodName,
                Parameters = args
            };

            if (useIpcRequestParameterType)
            {
                var parameterTypesByName = new IpcRequestParameterType[methodParams.Length];
                for (int i = 0; i < methodParams.Length; i++)
                {
                    parameterTypesByName[i] = new IpcRequestParameterType(methodParams[i].ParameterType);
                }

                request.ParameterTypesByName = parameterTypesByName;
            }
            else
            {
                var parameterTypes = new Type[methodParams.Length];
                for (int i = 0; i < args.Length; i++)
                {
                    parameterTypes[i] = methodParams[i].ParameterType;
                }

                request.ParameterTypes = parameterTypes;
            }

            return(request);
        }
        /// <summary>
        /// Creates the IPC request.
        /// </summary>
        /// <param name="methodName">Name of the method.</param>
        /// <param name="args">The arguments to the method.</param>
        /// <returns>IpcRequest object</returns>
        protected static IpcRequest CreateIpcRequest(string methodName, params object[] args)
        {
            MethodBase method = null;

            // Try to find the matching method based on name and args
            try
            {
                if (args.All(x => x != null))
                {
                    method = typeof(FactoryOrchestratorClient).GetMethod(methodName, args.Select(x => x.GetType()).ToArray());
                }

                if (method == null)
                {
                    method = typeof(FactoryOrchestratorClient).GetMethod(methodName);
                }
            }
            catch (Exception)
            {
                method = null;
            }

            if (method == null)
            {
                // Multiple methods with the same name were found or no method was found, try to find the unique method via stack trace
                var frame = new StackTrace().GetFrames().Where(x => x.GetMethod()?.Name == methodName);

                if (!frame.Any())
                {
                    throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.NoMethodFound, methodName));
                }
                if (frame.Count() > 1)
                {
                    throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.TooManyMethodsFound, methodName));
                }

                method = frame.First().GetMethod();
            }

            var methodParams   = method.GetParameters();
            var parameterTypes = new IpcRequestParameterType[methodParams.Length];

            for (int i = 0; i < methodParams.Length; i++)
            {
                parameterTypes[i] = new IpcRequestParameterType(methodParams[i].ParameterType);
            }

            var request = new IpcRequest()
            {
                MethodName           = methodName,
                Parameters           = args,
                ParameterTypesByName = parameterTypes
            };

            return(request);
        }
        private IpcRequest GetRequest(Expression exp, TInterface proxy)
        {
            if (!(exp is LambdaExpression lambdaExp))
            {
                throw new ArgumentException("Only support lambda expression, ex: x => x.GetData(a, b)");
            }

            if (!(lambdaExp.Body is MethodCallExpression methodCallExp))
            {
                throw new ArgumentException("Only support calling method, ex: x => x.GetData(a, b)");
            }

            Delegate @delegate = lambdaExp.Compile();

            @delegate.DynamicInvoke(proxy);

            if (_options.UseSimpleTypeNameAssemblyFormatHandling)
            {
                IpcRequestParameterType[] paramByName   = null;
                IpcRequestParameterType[] genericByName = null;

                var parameterTypes = (proxy as IpcProxy).LastInvocation.Method.GetParameters().Select(p => p.ParameterType);

                if (parameterTypes.Any())
                {
                    paramByName = new IpcRequestParameterType[parameterTypes.Count()];
                    int i = 0;
                    foreach (var type in parameterTypes)
                    {
                        paramByName[i++] = new IpcRequestParameterType(type);
                    }
                }

                var genericTypes = (proxy as IpcProxy).LastInvocation.Method.GetGenericArguments();

                if (genericTypes.Length > 0)
                {
                    genericByName = new IpcRequestParameterType[genericTypes.Count()];
                    int i = 0;
                    foreach (var type in genericTypes)
                    {
                        genericByName[i++] = new IpcRequestParameterType(type);
                    }
                }


                return(new IpcRequest
                {
                    MethodName = (proxy as IpcProxy).LastInvocation.Method.Name,
                    Parameters = (proxy as IpcProxy).LastInvocation.Arguments,

                    ParameterTypesByName = paramByName,
                    GenericArgumentsByName = genericByName
                });
            }
            else
            {
                return(new IpcRequest
                {
                    MethodName = (proxy as IpcProxy).LastInvocation.Method.Name,
                    Parameters = (proxy as IpcProxy).LastInvocation.Arguments,

                    ParameterTypes = (proxy as IpcProxy).LastInvocation.Method.GetParameters()
                                     .Select(p => p.ParameterType)
                                     .ToArray(),


                    GenericArguments = (proxy as IpcProxy).LastInvocation.Method.GetGenericArguments(),
                });
            }
        }