Exemple #1
0
        private MethodDescription GetMethodDescription(MethodInfo methodInfo)
        {
            MethodDescription methodDescription = null;

            if (!MethodDescriptions.TryGetValue(methodInfo, out methodDescription))
            {
                lock (MethodDescriptions)
                {
                    if (!MethodDescriptions.TryGetValue(methodInfo, out methodDescription))
                    {
                        var routeAttribute = methodInfo.GetCustomAttribute <RouteAttribute>();

                        if (routeAttribute == null)
                        {
                            throw new NotSupportedException(string.Format(MsgMissingSomethingOn, methodInfo.DeclaringType.ToString(), typeof(RouteAttribute).ToString(), methodInfo.ToString()));
                        }

                        var httpMethodAttribute = methodInfo.GetCustomAttributes().FirstOrDefault(t => t is IHttpMethodAttribute) as IHttpMethodAttribute;

                        if (httpMethodAttribute == null)
                        {
                            throw new NotSupportedException(string.Format(MsgMissingSomethingOn, methodInfo.DeclaringType.ToString(), typeof(IHttpMethodAttribute).ToString(), methodInfo.ToString()));
                        }

                        var httpMethod          = httpMethodAttribute.HttpMethod;
                        var pathParamNames      = ExtractParameterNames(routeAttribute.Path);
                        var parameters          = methodInfo.GetParameters();
                        var attributedParameter = parameters
                                                  .Where(p => p.GetCustomAttributes().Any(a => a is IParameterScopeAttribute) && !p.IsDefined(typeof(HttpIgnoreAttribute)))
                                                  .Select(p => new ParameterDescription()
                        {
                            ParameterInfo   = p,
                            ScopeAttributes = p.GetCustomAttributes().Where(a => a is IParameterScopeAttribute)
                                              .Cast <IParameterScopeAttribute>().ToArray(),
                            Order = Array.IndexOf(parameters, p)
                        }).ToList();

                        var unhandledPathParamNames = pathParamNames.ToList();
                        foreach (var p in attributedParameter)
                        {
                            foreach (var a in p.ScopeAttributes)
                            {
                                if (a is PathParamAttribute)
                                {
                                    var name = a.Name ?? p.ParameterInfo.Name;
                                    if (unhandledPathParamNames.RemoveAll(i => string.Equals(i, name, StringComparison.OrdinalIgnoreCase)) > 0)
                                    {
                                        ((PathParamAttribute)a).PathParamNamesFilter = new string[] { name };
                                    }
                                    else
                                    {
                                        ((PathParamAttribute)a).PathParamNamesFilter = pathParamNames;
                                    }
                                }
                            }
                        }
                        var nonAttributedParameter = parameters.Where(p => !p.GetCustomAttributes().Any(a => a is IParameterScopeAttribute) && !p.IsDefined(typeof(HttpIgnoreAttribute)))
                                                     .Select(
                            p =>
                        {
                            var attrList = new List <IParameterScopeAttribute>();
                            if (unhandledPathParamNames.Any())
                            {
                                attrList.Add(new PathParamAttribute()
                                {
                                    PathParamNamesFilter = unhandledPathParamNames.ToArray()
                                });
                            }

                            attrList.Add(ParameterScopeAttributeFactory.CreateByHttpMethod(httpMethod, p));

                            return(new ParameterDescription()
                            {
                                ParameterInfo = p,
                                ScopeAttributes = attrList.ToArray(),
                                Order = Array.IndexOf(parameters, p)
                            });
                        }
                            ).ToList();

                        var httpRetryAttr = methodInfo.GetCustomAttribute <HttpRetryAttribute>();
                        methodDescription = new MethodDescription(methodInfo)
                        {
                            HttpMethod        = httpMethod,
                            AuthorizeRequired = (_config.AuthorizeRequired ||
                                                 methodInfo.IsDefined(typeof(AuthorizeAttribute))) &&
                                                !methodInfo.IsDefined(typeof(AllowAnonymousAttribute)),
                            Route                 = routeAttribute.Path,
                            MaxRetry              = httpRetryAttr != null ? httpRetryAttr.MaxRetry : _config.HttpClientSettings.MaxRetry,
                            ActionFilters         = _config.HttpClientSettings.ActionFilters.Concat(methodInfo.GetCustomAttributes().Where(a => a is IActionFilter).Cast <IActionFilter>().OrderBy(i => i.Order)).ToArray(),
                            Parameters            = attributedParameter.Union(nonAttributedParameter).ToArray(),
                            ReturnTypeDescription = new ReturnTypeDescription()
                        };

                        var returnType = methodInfo.ReturnType;
                        methodDescription.ReturnTypeDescription.ReturnType        = methodInfo.ReturnType;
                        methodDescription.ReturnTypeDescription.TargetObjectType  = methodInfo.ReturnType;
                        methodDescription.ReturnTypeDescription.HttpResultDecoder = methodInfo.GetCustomAttributes().FirstOrDefault(c => c is IHttpResultDecoder) as IHttpResultDecoder ?? _config.HttpClientSettings.HttpResultDecoder;

                        if (typeof(Task).IsAssignableFrom(returnType) && returnType.IsGenericType)
                        {
                            var taskObjectType = returnType.GenericTypeArguments[0];
                            if (typeof(IHttpResult).IsAssignableFrom(taskObjectType))
                            {
                                /************
                                 * Task<IHttpResult<TResult>>,
                                 * Task<IHttpResult>
                                 * ***********/
                                if (taskObjectType.IsGenericType)
                                {
                                    methodDescription.ReturnTypeDescription.HttpResultType   = taskObjectType.IsClass ? taskObjectType : typeof(HttpResult <>);
                                    methodDescription.ReturnTypeDescription.TargetObjectType = taskObjectType.GenericTypeArguments[0];
                                }
                                else
                                {
                                    methodDescription.ReturnTypeDescription.HttpResultType   = taskObjectType.IsClass ? taskObjectType : typeof(HttpResult <>);
                                    methodDescription.ReturnTypeDescription.TargetObjectType = typeof(object);
                                }

                                methodDescription.MethodResultConveter = (httpResultTask) =>
                                {
                                    var result = CastHttpResultTaskMethod.MakeGenericMethod(taskObjectType).Invoke(null, new object[] { httpResultTask() });
                                    return(result);
                                };
                            }
                            else
                            {
                                /*************
                                 * Task<TResult>
                                 * *************/
                                methodDescription.ReturnTypeDescription.TargetObjectType = returnType.GenericTypeArguments[0];

                                methodDescription.MethodResultConveter = (httpResultTask) =>
                                {
                                    var result = CastObjectTaskMethod.MakeGenericMethod(taskObjectType).Invoke(null, new object[] { httpResultTask() });
                                    return(result);
                                };
                            }
                        }
                        else if (typeof(Task).IsAssignableFrom(returnType))
                        {
                            /*************
                             * Task
                             * *************/

                            var taskObjectType = typeof(void);
                            methodDescription.ReturnTypeDescription.TargetObjectType = typeof(object);

                            methodDescription.MethodResultConveter = (httpResultTask) =>
                            {
                                return(httpResultTask().Then(t =>
                                {
                                    if (!t.IsSuccessStatusCode)
                                    {
                                        //TODO  throw new HttpException((int)t.StatusCode, t.ReasonPhrase);
                                    }
                                }));
                            };
                        }
                        else if (typeof(IHttpResult).IsAssignableFrom(returnType))
                        {
                            /*************
                             * IHttpResult<TResult>
                             * IHttpResult
                             * ************/

                            var taskObjectType = returnType;
                            if (returnType.IsGenericType)
                            {
                                methodDescription.ReturnTypeDescription.HttpResultType   = returnType.IsClass ? returnType : typeof(HttpResult <>);
                                methodDescription.ReturnTypeDescription.TargetObjectType = returnType.GenericTypeArguments[0];
                            }
                            else
                            {
                                methodDescription.ReturnTypeDescription.HttpResultType   = returnType.IsClass ? returnType : typeof(HttpResult <>);
                                methodDescription.ReturnTypeDescription.TargetObjectType = typeof(object);
                            }
                            methodDescription.MethodResultConveter = (httpResultTask) =>
                            {
                                var result = Task.Run(httpResultTask).Result;
                                return(ObjectExtensions.ChangeType(result, returnType));
                            };
                        }
                        else if (returnType == typeof(void))
                        {
                            /*************
                            * void
                            * ***********/
                            var taskObjectType = typeof(void);
                            methodDescription.ReturnTypeDescription.TargetObjectType = typeof(object);

                            methodDescription.MethodResultConveter = (httpResultTask) =>
                            {
                                var t = Task.Run(httpResultTask).Result;
                                if (!t.IsSuccessStatusCode)
                                {
                                    //TODO throw new HttpException((int)t.StatusCode, t.ReasonPhrase);
                                }
                                return(null);
                            };
                        }
                        else
                        {
                            /***********
                             * TResult
                             * object
                             * ************/

                            var taskObjectType = returnType;
                            methodDescription.ReturnTypeDescription.TargetObjectType = returnType;

                            methodDescription.MethodResultConveter = (httpResultTask) =>
                            {
                                var result = Task.Run(httpResultTask).Result.Content;
                                return(ObjectExtensions.ChangeType(result, returnType));
                            };
                        }

                        methodDescription.HttpResultConverter = (httpTask, actionContext) =>
                        {
                            return(httpTask.ToHttpResult(methodDescription.ReturnTypeDescription.TargetObjectType, actionContext));
                        };

                        methodDescription.MultiPartAttribute = methodInfo.GetCustomAttribute <MultiPartAttribute>();

                        MethodDescriptions.Add(methodInfo, methodDescription);
                    }
                }
            }

            return(methodDescription);
        }