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); }
/// <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); }
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); }