private void FillQueryStrings(RestRequest request, RestInfo info, object[] args)
        {
            if (info.QueryStringInfos != null)
            {
                foreach (var qs in info.QueryStringInfos)
                {
                    if (qs.ArgPosition == -1)
                    {
                        var value = qs.Converter != null?qs.Converter.Convert(qs.DefaultValue) : qs.DefaultValue;

                        request.AddQueryParameter(qs.Name, value.ToString());
                    }
                    else if (qs.DefaultValue != args[qs.ArgPosition] || !qs.IgnoreIfDefault)
                    {
                        var value = args[qs.ArgPosition];
                        if (value is IEnumerable <object> )
                        {
                            foreach (var v in value as IEnumerable <object> )
                            {
                                request.AddParameter(qs.Name, v.ToString());
                            }
                        }
                        else
                        {
                            if (qs.Converter != null)
                            {
                                value = qs.Converter.Convert(value);
                            }
                            request.AddQueryParameter(qs.Name, value.ToString());
                        }
                    }
                }
            }
        }
 private void FillUrlSegments(RestRequest request, RestInfo info, object[] args)
 {
     if (info.UrlSegmentInfos != null)
     {
         foreach (var urlSegment in info.UrlSegmentInfos)
         {
             request.AddUrlSegment(urlSegment.Name, args[urlSegment.ArgPosition]);
         }
     }
 }
        private void FillPostBody(RestRequest request, RestInfo info, object[] args)
        {
            if (info.PostInfos != null)
            {
                foreach (var p in info.PostInfos)
                {
                    if (p.IsFile)
                    {
                        if (args[p.ArgPosition] is IEnumerable <string> )
                        {
                            var files = args[p.ArgPosition] as IEnumerable <string>;
                            foreach (var file in files)
                            {
                                request.AddFile(p.Name, file);
                            }
                        }
                        else
                        {
                            request.AddFile(p.Name, args[p.ArgPosition].ToString());
                        }
                    }
                    else if (p.ArgPosition == -1)
                    {
                        var value = p.Converter != null?p.Converter.Convert(p.DefaultValue) : p.DefaultValue;

                        request.AddParameter(p.Name, value.ToString());
                    }
                    else if (p.DefaultValue != args[p.ArgPosition] || !p.IgnoreIfDefault)
                    {
                        var value = args[p.ArgPosition];
                        if (p.Converter != null)
                        {
                            value = p.Converter.Convert(value);
                        }

                        if (value is IEnumerable <object> )
                        {
                            foreach (var v in value as IEnumerable <object> )
                            {
                                request.AddParameter(p.Name, v.ToString());
                            }
                        }
                        else
                        {
                            request.AddParameter(p.Name, value);
                        }
                    }
                }
            }
        }
 private void FillHeaders(RestRequest request, RestInfo info, object[] args)
 {
     if (info.HeaderInfos != null)
     {
         foreach (var headerInfo in info.HeaderInfos)
         {
             var template = new string(headerInfo.Template);
             foreach (var tuple in headerInfo.ArgPositions)
             {
                 template = template.Replace(WrapWithVariableChars(tuple.Item1), args[tuple.Item2].ToString());
             }
             request.AddHeader(headerInfo.Name, template);
         }
     }
 }
        private void Initialize(T decorated)
        {
            if (decorated == null)
            {
                throw new ArgumentNullException(nameof(decorated));
            }

            _decorated = decorated;
            restClient = new RestClient(_decorated.ServiceRoot);

            // 以下的都是用来解析各种 Attribute,将信息存到 methodMap 里
            var headerAttributeType         = typeof(RequestHeaderAttribute);
            var restAttributeType           = typeof(RestAttribute);
            var forHeaderAttributeType      = typeof(ForHeaderAttribute);
            var forQueryStringAttributeType = typeof(ForQueryStringAttribute);
            var forParameterAttributeType   = typeof(ForParameterAttribute);
            var forUrlSegmentAttributeType  = typeof(ForUrlSegmentAttribute);
            var destructAttributeType       = typeof(DestructureAttribute);

            var methods = _decorated.GetType().GetMethods();

            foreach (var method in methods)
            {
                if (!(method.GetCustomAttribute <RestAttribute>() is RestAttribute restAttribute))
                {
                    continue;
                }

                var methodInfo = new RestInfo();
                methodInfo.HttpMethod    = restAttribute.Method;
                methodInfo.UrlTemplate   = restAttribute.Template;
                methodInfo.IsAbsoluteUrl = restAttribute.IsAbsoluteUrl;
                methodInfo.IsAsync       = IsAsyncMethod(method);

                var headerAttributes = method.GetCustomAttributes <RequestHeaderAttribute>();
                var parameterInfos   = method.GetParameters();
                if (headerAttributes.Any())
                {
                    methodInfo.HeaderInfos = headerAttributes.Select(
                        h => new HeaderInfo
                    {
                        Name         = h.Key,
                        Template     = h.ValueTemplate,
                        ArgPositions = ParseRouteFormat(h.ValueTemplate).Select(
                            s => parameterInfos.Where(pi => pi.Name == s).First()
                            ).Select(pi => new Tuple <string, int>(pi.Name, pi.Position)).ToArray()
                    }
                        ).ToArray();
                }

                var i               = 0;
                var paramInfos      = new List <ParamInfo>();
                var postInfos       = new List <PostInfo>();
                var urlSegmentInfos = new List <ParamInfo>();

                var methodPostInfos = method.GetCustomAttributes <ForParameterAttribute>();
                if (methodPostInfos != null && methodPostInfos.Any())
                {
                    foreach (var pp in methodPostInfos)
                    {
                        postInfos.Add(new PostInfo
                        {
                            Name            = pp.Name,
                            ArgPosition     = -1,
                            IsFile          = false,
                            IgnoreIfDefault = false,
                            DefaultValue    = pp.Value,
                            Converter       = pp.ConverterType != null ? Activator.CreateInstance(pp.ConverterType) as ISeafileValueConverter : null
                        });
                    }
                }

                var methodParamInfos = method.GetCustomAttributes <ForQueryStringAttribute>();
                if (methodParamInfos != null && methodParamInfos.Any())
                {
                    foreach (var p in methodParamInfos)
                    {
                        paramInfos.Add(new ParamInfo
                        {
                            Name            = p.Name,
                            ArgPosition     = -1,
                            IgnoreIfDefault = false,
                            DefaultValue    = p.Value,
                            Converter       = p.ConverterType != null ? Activator.CreateInstance(p.ConverterType) as ISeafileValueConverter : null
                        });
                    }
                }

                foreach (var pi in parameterInfos)
                {
                    if (pi.GetCustomAttribute(forParameterAttributeType) is ForParameterAttribute pp)
                    {
                        postInfos.Add(new PostInfo
                        {
                            Name            = pp.Name ?? pi.Name,
                            ArgPosition     = i,
                            IsFile          = pp.IsFile,
                            IgnoreIfDefault = pp.IgnoreIfDefault,
                            DefaultValue    = pi.DefaultValue,
                            Converter       = pp.ConverterType != null ? Activator.CreateInstance(pp.ConverterType) as ISeafileValueConverter : null
                        });
                    }

                    if (pi.GetCustomAttribute(forQueryStringAttributeType) is ForQueryStringAttribute pq)
                    {
                        paramInfos.Add(new ParamInfo
                        {
                            Name            = pq.Name ?? pi.Name,
                            ArgPosition     = i,
                            IgnoreIfDefault = pq.IgnoreIfDefault,
                            DefaultValue    = pi.DefaultValue,
                            Converter       = pq.ConverterType != null ? Activator.CreateInstance(pq.ConverterType) as ISeafileValueConverter : null
                        });;
                    }

                    if (pi.GetCustomAttribute(forUrlSegmentAttributeType) is ForUrlSegmentAttribute pu)
                    {
                        urlSegmentInfos.Add(new ParamInfo
                        {
                            Name        = pu.Name ?? pi.Name,
                            ArgPosition = i
                        });
                    }
                    i++;
                }

                methodInfo.PostInfos        = postInfos.ToArray();
                methodInfo.QueryStringInfos = paramInfos.ToArray();
                methodInfo.UrlSegmentInfos  = urlSegmentInfos.ToArray();
                methodMap.Add(method.Name, methodInfo);

                var destructureAttribute = method.GetCustomAttribute(destructAttributeType) as DestructureAttribute;
                if (destructureAttribute != null)
                {
                    var    dictType     = typeof(Dictionary <,>);
                    Type[] types        = { typeof(string), method.ReturnType };
                    var    tempType     = dictType.MakeGenericType(types);
                    var    propertyInfo = tempType.GetProperty("Item");

                    destructureMap.Add(method.Name, new DestructureInfo
                    {
                        Key       = destructureAttribute.Key,
                        Type      = tempType,
                        ItemsProp = propertyInfo
                    });
                }
            }
        }