public ArangoResponse <T> Send <T>(IOperationThatReturns <T> operation)
        {
            string typeName = operation.GetType().Name;

            try
            {
                _logger.Trace("Sending {0} operation", typeName);

                DateTime begin = DateTime.UtcNow;

                ArangoResponse <T> arangoResponse = _restDispatcher.Send(operation);

                DateTime end = DateTime.UtcNow;

                arangoResponse.Status.TotalDuration = end - begin;

                _logger.Trace("Operation {0} completed successfully in {1}ms", typeName, arangoResponse.Status.TotalDuration.TotalMilliseconds);

                if (_settings.ThrowExceptions)
                {
                    arangoResponse.ThrowIfError();
                }

                return(arangoResponse);
            }
            catch (Exception e)
            {
                _logger.TraceException(string.Format("Operation {0} fail", typeName), e);

                throw;
            }
        }
        private ArangoResponse <T> PostExecute <T>(IOperationThatReturns <T> operation, HttpResponseMessage response)
        {
            var contentTask = response.Content.ReadAsStringAsync();

            contentTask.Wait();

            var content = contentTask.Result;

            if (string.IsNullOrWhiteSpace(content))
            {
                throw new InvalidOperationException("Response Content is empty");
            }

            JObject deserializeObject = JsonConvert.DeserializeObject <JObject>(content);

            var responseStatus = new ArangoResponseStatus
            {
                Error        = deserializeObject.GetValueSafe <bool>("error"),
                Code         = deserializeObject.GetValueSafe <int>("code"),
                ErrorMessage = deserializeObject.GetValueSafe <string>("errorMessage"),
                ErrorNum     = deserializeObject.GetValueSafe <int>("errorNum"),
                StatusCode   = response.StatusCode
            };

            var typedResponse = new ArangoResponse <T>
            {
                Status = responseStatus
            };

            if (responseStatus.Error)
            {
                return(typedResponse);
            }

            var afterComplete = operation as IGetResultAfterExecution <T>;

            if (afterComplete != null)
            {
                var result = afterComplete.GetResult(deserializeObject, typedResponse);

                typedResponse.Result = result;
            }
            else
            {
                JToken result;

                if (!(operation is IIgnoreResultField) && deserializeObject.TryGetValue("result", out result))
                {
                    typedResponse.Result = result.ToObject <T>();
                }
                else
                {
                    typedResponse.Result = deserializeObject.ToObject <T>();
                }
            }

            return(typedResponse);
        }
        private HttpRequestMessage GetRequest <T>(IOperationThatReturns <T> operation)
        {
            var resource = operation.Resource.Resource;

            var withParameters = operation as IWithUrlParameters;

            if (withParameters != null)
            {
                var parameters = withParameters.GetUrlParameters();

                resource = resource.TokenReplace(parameters);
            }

            HttpRequestMessage request = new HttpRequestMessage(operation.Resource.Method, resource);

            var withBody = operation as IWithBody;

            if (withBody != null)
            {
                object body = withBody.GetBody();

                if (body is Stream)
                {
                    request.Content = new StreamContent((Stream)body);

                    return(request);
                }

                string json;

                if (body is string)
                {
                    json = body.ToString();
                }
                else
                {
                    json = JsonConvert.SerializeObject(body);
                }

                request.Content = new StringContent(json, Encoding.UTF8, "application/json");
            }

            return(request);
        }
        public ArangoResponse <T> Send <T>(IOperationThatReturns <T> operation)
        {
            using (var request = GetRequest(operation))
            {
                DateTime begin = DateTime.UtcNow;
                DateTime end;

                ArangoResponse <T> arangoResponse;

                using (var response = _client.SendAsync(request))
                {
                    response.Wait();

                    end = DateTime.UtcNow;

                    arangoResponse = PostExecute(operation, response.Result);
                }

                arangoResponse.Status.ServerDuration = end - begin;

                return(arangoResponse);
            }
        }