Example #1
0
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            Debug.Assert(binder != null);
            Debug.Assert(args != null);

            if (binder.IsVerb())
            {
                // build a rest request based on this instance, parent instances and invocation arguments
                var builder = new RequestBuilder(this);
                var request = builder.BuildRequest(binder, args);

                // the binder name (i.e. the dynamic method name) is the verb
                // example: proxy.locations.get() binder.Name == "get"
                var invocation = new RestInvocation(_client, binder.Name);
                result = invocation.InvokeAsync(request); // this will return a Task<dynamic> with the rest async call
            }
            else
            {
                if (args.Length != 1)
                {
                    throw new InvalidOperationException("The segment escape sequence must have exactly 1 unnamed parameter");
                }

                // this is for when we escape a url segment by passing it as an argument to a method invocation
                // example: proxy.segment1("escaped")
                // here we create two new dynamic objects, 1 for "segment1" which is the method name
                // and then we create one for the escaped segment passed as an argument - "escaped" in the example
                var tmp = new RestProxy(_client, this, binder.Name, KeywordEscapeCharacter);
                result = new RestProxy(_client, tmp, args[0].ToString(), KeywordEscapeCharacter);
            }

            return(true);
        }
Example #2
0
        /// <summary>
        /// <see cref="System.Dynamic.DynamicObject.TryInvokeMember(InvokeMemberBinder, object[], out object)"/>
        /// </summary>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            Debug.Assert(binder != null);
            Debug.Assert(args != null);

            if (binder.IsVerb())
            {
                // parse out the details of the invocation and have the derived class create a Task
                result = CreateVerbAsyncTask(binder.Name, binder.GetUnnamedArgs(args), binder.GetNamedArgs(args));
            }
            else
            {
                if (args.Length != 1)
                {
                    throw new InvalidOperationException("The segment escape sequence must have exactly 1 unnamed parameter");
                }

                // this is for when we escape a url segment by passing it as an argument to a method invocation
                // example: proxy.segment1("escaped")
                // here we create two new dynamic objects, 1 for "segment1" which is the method name
                // and then we create one for the escaped segment passed as an argument - "escaped" in the example
                var tmp = CreateProxyNode(this, binder.Name);
                result = CreateProxyNode(tmp, args[0].ToString());
            }

            return(true);
        }
        /// <summary>
        /// <see cref="System.Dynamic.DynamicObject.TryInvokeMember(InvokeMemberBinder, object[], out object)"/>
        /// </summary>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            if (binder.IsVerb()) // the method name is one of our http verbs - invoke as such
            {
                var unnamedArgs = binder.GetUnnamedArgs(args);

                // filter our sentinal types out of the unnamed args to be passed on the request
                var requestArgs = unnamedArgs.Where(arg => !arg.IsOfType(_reservedTypes));

                // these are the objects that can be passed as unnamed args that we use intenrally and do not pass to the request
                var cancelToken           = unnamedArgs.OfType <CancellationToken>().DefaultIfEmpty(CancellationToken.None).First();
                var serializationSettings = unnamedArgs.OfType <JsonSerializerSettings>().FirstOrNewInstance();

#if EXPERIMENTAL_GENERICS
                // dig the generic type argument out of the binder
                var returnType = binder.GetGenericTypeArguments().FirstOrDefault(); // evil exists within that method
#else
                var returnType = unnamedArgs.OfType <Type>().FirstOrDefault();
#endif
                // if no return type argument provided there is no need for late bound method dispatch
                if (returnType == null)
                {
                    // no return type argumentso return result deserialized as dynamic
                    // parse out the details of the invocation and have the derived class create a Task
                    result = CreateVerbAsyncTask <dynamic>(binder.Name, requestArgs, binder.GetNamedArgs(args), cancelToken, serializationSettings);
                }
                else
                {
                    // we got a type argument (like this if experimental: client.get<SomeType>(); or like this normally: client.get(typeof(SomeType)); )
                    // make and invoke the generic implementaiton of the CreateVerbAsyncTask method
                    var methodInfo = this.GetType().GetTypeInfo().GetDeclaredMethod("CreateVerbAsyncTask");
                    var method     = methodInfo.MakeGenericMethod(returnType);
                    result = method.Invoke(this, new object[] { binder.Name, requestArgs, binder.GetNamedArgs(args), cancelToken, serializationSettings });
                }
            }
            else // otherwise the method is yet another uri segment
            {
                if (args.Length != 1)
                {
                    throw new InvalidOperationException("The segment escape sequence must have exactly 1 unnamed parameter");
                }

                // this is for when we escape a url segment by passing it as an argument to a method invocation
                // example: proxy.segment1("escaped")
                // here we create two new dynamic objects, 1 for "segment1" which is the method name
                // and then we create one for the escaped segment passed as an argument - "escaped" in the example
                var tmp = CreateProxyNode(this, binder.Name);
                result = CreateProxyNode(tmp, args[0].ToString());
            }

            return(true);
        }
Example #4
0
        public RestRequest BuildRequest(InvokeMemberBinder binder, object[] args)
        {
            Debug.Assert(binder.IsVerb());

            // total number of segments is the number or parts of the call chain not including the root
            // example: proxy.location.geo.get() has two url segments - the verb doesn't count
            // Index is zero based so add one
            string template = CreateUrlSegmentTemplate(_proxy.Index + 1);

            var request = new RestRequest(template);

            request.RequestFormat = DataFormat.Json; // we only talk json
            request.AddHeader("Accept", "application/json, text/json, text/x-json, text/javascript");

            // fill in the url segments with the names of each call chain member
            _proxy.AddSegment(request); // this recurses up the instance chain

            int unnamedArgCount = binder.UnnamedArgCount();

            // all named arguments are added as parameters
            for (int i = 0; i < binder.CallInfo.ArgumentNames.Count; i++)
            {
                var arg = args[i + unnamedArgCount];
                if (arg is IDictionary <string, object> ) // if the arg is a dictionary, add each item as a parameter key value pair
                {
                    request.AddDictionary((IDictionary <string, object>)arg);
                }
                else
                {
                    request.AddParameter(binder.CallInfo.ArgumentNames[i].TrimStart(_proxy.KeywordEscapeCharacter), arg);
                }
            }

            // all unnamed args get added to the request body
            for (int i = 0; i < unnamedArgCount; i++)
            {
                request.AddBody(args[i]);
            }

            return(request);
        }