public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var info   = binder.CallInfo;
            var method = binder.Name;

            // accepting named args only... SKEET!
            if (info.ArgumentNames.Count != args.Length)
            {
                throw new InvalidOperationException("Please use named arguments.");
            }

            //stuff parameters into case insensitive dictionary
            var parameters = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

            for (int i = 0; i < args.Length; i++)
            {
                parameters.Add(info.ArgumentNames[i], args[i]);
            }

            var request = _jsonUtility.GetJsonRequest(_serviceName, method, parameters);

            result = _client.Execute(AsyncServiceName, AsyncProcessMethod, new Dictionary <string, object> {
                { "request", request }
            });


            return(true);
        }
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var method        = binder.Name;
            var argumentNames = binder.CallInfo.ArgumentNames;

            // accept named args only
            if (argumentNames.Count != args.Length)
            {
                throw new InvalidOperationException("Please use named arguments. Example: myObject.MyMethod(myNamedParameter: 123);");
            }

            //stuff parameters into case insensitive dictionary
            var parameters = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

            for (int i = 0; i < args.Length; i++)
            {
                parameters.Add(argumentNames[i], args[i]);
            }

            //the only way to determine if generic type parameters have been used is reflection
            var  csharpBinder = binder.GetType().GetInterface("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder");
            var  typeArgs     = csharpBinder.GetProperty("TypeArguments").GetValue(binder, null) as IList <Type>;
            Type returnType   = typeArgs.FirstOrDefault();

            //if it exists, the first generic type parameter is our return type (e.g. myObject.MyMethod<int>(Id: 123); --> returnType would be typeof(int))
            if (returnType != null)
            {
                MethodInfo methodInfo        = typeof(JsonRPCHttpClient).GetMethod("ExecuteAndConvert");
                MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(returnType);
                try
                {
                    result = genericMethodInfo.Invoke(_client, new object[] { _serviceName, method, parameters });
                }
                catch (TargetInvocationException tiex)
                {
                    throw tiex.InnerException;
                }
            }
            else
            {
                result = _client.Execute(_serviceName, method, parameters);
            }

            return(true);
        }