public static string DiagName(this IReturn value, DiagContextInternal ctx)
        {
            var unknown = $"<UNKNOWN|{value.GetType().DiagName()}>";

            if (value is ReturnValue rvs)
            {
                return(ReflectionReader.ReadFieldValue(
                           rvs,
                           "_value",
                           (object o) => o.GetObjectId(ctx),
                           "<VALUE|CANNOT_READ>"));
            }

            var valueType = value.GetType();

            if (!valueType.IsGenericType)
            {
                return(unknown);
            }

            var gtd = valueType.GetGenericTypeDefinition();

            if (gtd == typeof(ReturnMultipleValues <>))
            {
                return(ReflectionReader.ReadFieldValue(
                           value,
                           "_valuesToReturn",
                           (IEnumerable objs) => objs.Cast <object>().Print(o => o.GetObjectId(ctx)),
                           "<MVALUES|CANNOT_READ>"));
            }

            if (gtd == typeof(ReturnValueFromFunc <>))
            {
                return(ReflectionReader.ReadFieldValue(
                           value,
                           "_funcToReturnValue",
                           (Delegate d) => $"<FUNC|{d.DiagName()}>",
                           "<FVALUE|CANNOT_READ>"));
            }

            if (gtd == typeof(ReturnMultipleFuncsValues <>))
            {
                return(ReflectionReader.ReadFieldValue(
                           value,
                           "_funcsToReturn",
                           (IEnumerable <Delegate> ds) => $"<FUNCS|{ds.Print(DiagName)}>",
                           "<FMVALUES|CANNOT_READ>"));
            }

            return(unknown);
        }
コード例 #2
0
ファイル: ServiceShack.cs プロジェクト: eteeselink/scandrop
        internal string BuildUri <T>(IReturn <T> request, Method method)
        {
            var type        = request.GetType().GetTypeInfo();
            var attrs       = type.GetCustomAttributes <RouteAttribute>(true);
            var validRoutes = attrs
                              .Where(attr => (attr.AcceptedMethods & method) == method)
                              .Select(attr => attr.UrlTemplate);

            var properties = type.DeclaredProperties
                             .ToDictionary(
                prop => String.Format("{{{0}}}", prop.Name),
                prop => prop.GetValue(request))
                             .Where(kvp => kvp.Value != null)
                             .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            var matchedRoutes = validRoutes.Select(route => MatchRoute(route, properties)).ToList();
            var highest       = matchedRoutes.Max(t => t.Item1);
            var bestRoutes    = matchedRoutes.Where(t => t.Item1 == highest);

            if (bestRoutes.Count() > 1)
            {
                // TODO: class
                throw new Exception("Ambiguous routes on type " + type.Name + ": " + String.Join(", ", validRoutes));
            }
            if (!bestRoutes.Any())
            {
                // TODO: class
                throw new Exception("Could not find any matching route on type " + type.Name);
            }
            return(baseUri + bestRoutes.Single().Item2);
        }
コード例 #3
0
        public static string GetUrlFromRoute <T>(this IReturn <T> request, bool setPropertiesAsUrlParams = false)
        {
            var requestType = request.GetType();

            var properties = requestType.GetTypeInfo().DeclaredProperties
                             .Select(property => new
            {
                property.Name,
                Value = property.GetValue(request)
            })
                             .Where(property => property.Value != null)
                             .ToArray();

            var routeAttributes = requestType.GetTypeInfo().GetCustomAttributes(typeof(RouteAttribute), true)
                                  .OfType <RouteAttribute>()
                                  .ToArray();

            if (routeAttributes.None())
            {
                return(string.Empty);
            }

            var routeAttribute = routeAttributes.Length == 1
                ? routeAttributes.First()
                : routeAttributes.SelectCorrectRouteAttribute(properties.Select(p => p.Name));

            // before PCL: var matches = Regex.Matches(routeAttribute.Address, "\\{[a-zA-Z]+\\}", RegexOptions.Compiled)
            var matches = Regex.Matches(routeAttribute.Address, "\\{[a-zA-Z]+\\}")
                          .Cast <Match>()
                          .Select(match => new
            {
                PropertyName = match.Value.Replace("{", "").Replace("}", ""),
                Tag          = match.Value
            })
                          .ToArray();

            var address = routeAttribute.Address;

            foreach (var match in matches)
            {
                var property = properties.First(p => p.Name == match.PropertyName);

                address = address.Replace(match.Tag, property.Value.ToString());
            }

            if (!setPropertiesAsUrlParams)
            {
                return(address);
            }

            var parameters = properties
                             .Where(prop => matches.None(match => prop.Name == match.PropertyName))
                             .Select(prop => prop.Name + "=" + Uri.EscapeUriString(prop.Value.ToString()))
                             .ToArray();

            return(parameters.Any()
                ? address + "?" + parameters.JoinBy("&")
                : address);
        }
コード例 #4
0
ファイル: RPCClient.cs プロジェクト: zhaopeiym/Talk
        /// <summary>
        /// 获取请求url
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static string GetUrl(this IReturn request, IRPCContext context = null)
        {
            var assemblyName = request.GetType().Assembly.GetName().Name;
            //这里约定配置BaseUrl (优先级 3)
            var baseUrl = ConfigurationManager.GetConfig($"ApiHost.{assemblyName}");

            //优先使用代码设置的bashUrl (优先级 2)
            if (!string.IsNullOrWhiteSpace(context?.RPCBaseUrl?.Trim()))
            {
                baseUrl = context.RPCBaseUrl;
            }

            var partUrl = request.GetType()
                          .GetCustomAttributes(false)
                          .OfType <RpcRouteAttribute>()
                          .Select(attr => attr).FirstOrDefault()?.Path ?? string.Empty;

            return(new Uri(new Uri(baseUrl), partUrl).ToString());
        }
コード例 #5
0
        protected TResponse ProcessRequest <TResponse>(IReturn <TResponse> request, HttpStatusCode code,
                                                       Func <TResponse> action) where TResponse : class
        {
            string requestType = (request != null) ? request.GetType().Name : string.Empty;

            //TODO: Audit this call in your analytics

            try
            {
                Guard.NotNull(() => request, request);

                TResponse response = null;
                response = action();

                if (response == null)
                {
                    throw new NotSupportedException();
                }

                SetResponseCode(code);

                //TODO: Audit this response in your analytics

                return(response);
            }
            catch (ArgumentException ex)
            {
                throw HttpErrorThrower.BadRequest(ex.Message);
            }
            catch (ResourceNotFoundException ex)
            {
                throw HttpErrorThrower.NotFound(ex.Message);
            }
            catch (ResourceConflictException ex)
            {
                throw HttpErrorThrower.Conflict(ex.Message);
            }
            catch (RuleViolationException ex)
            {
                throw HttpErrorThrower.BadRequest(ex.Message);
            }
            catch (Exception)
            {
                throw HttpErrorThrower.InternalServerError();
            }
        }
コード例 #6
0
        public static string ToUrl(this IReturn request, string httpMethod, string formatFallbackToPredefinedRoute = null)
        {
            httpMethod = httpMethod.ToUpper();

            var requestType   = request.GetType();
            var requestRoutes = routesCache.GetOrAdd(requestType, GetRoutesForType);

            if (!requestRoutes.Any())
            {
                if (formatFallbackToPredefinedRoute == null)
                {
                    throw new InvalidOperationException("There is no rest routes mapped for '{0}' type. ".Fmt(requestType)
                                                        + "(Note: The automatic route selection only works with [Route] attributes on the request DTO and"
                                                        + "not with routes registered in the IAppHost!)");
                }

                var predefinedRoute = "/{0}/syncreply/{1}".Fmt(formatFallbackToPredefinedRoute, request.GetType().Name);
                if (httpMethod == "GET" || httpMethod == "DELETE" || httpMethod == "OPTIONS")
                {
                    var queryString = "?{0}".Fmt(request.GetType().GetProperties().ToQueryString(request));
                    predefinedRoute += queryString;
                }

                return(predefinedRoute);
            }

            var routesApplied =
                requestRoutes.Select(route => new { Route = route, Result = route.Apply(request, httpMethod) }).ToList();
            var matchingRoutes = routesApplied.Where(x => x.Result.Matches).ToList();

            if (!matchingRoutes.Any())
            {
                var errors = string.Join(String.Empty, routesApplied.Select(x => "\r\n\t{0}:\t{1}".Fmt(x.Route.Path, x.Result.FailReason)).ToArray());
                var errMsg = "None of the given rest routes matches '{0}' request:{1}"
                             .Fmt(requestType.Name, errors);

                throw new InvalidOperationException(errMsg);
            }

            var matchingRoute = matchingRoutes[0]; // hack to determine variable type.

            if (matchingRoutes.Count > 1)
            {
                var mostSpecificRoute = FindMostSpecificRoute(matchingRoutes.Select(x => x.Route));
                if (mostSpecificRoute == null)
                {
                    var errors = String.Join(String.Empty, matchingRoutes.Select(x => "\r\n\t" + x.Route.Path).ToArray());
                    var errMsg = "Ambiguous matching routes found for '{0}' request:{1}".Fmt(requestType.Name, errors);
                    throw new InvalidOperationException(errMsg);
                }

                matchingRoute = matchingRoutes.Single(x => x.Route == mostSpecificRoute);
            }
            else
            {
                matchingRoute = matchingRoutes.Single();
            }

            var url = matchingRoute.Result.Uri;

            if (httpMethod == HttpMethod.Get || httpMethod == HttpMethod.Delete)
            {
                var queryParams = matchingRoute.Route.FormatQueryParameters(request);
                if (!String.IsNullOrEmpty(queryParams))
                {
                    url += "?" + queryParams;
                }
            }

            return(url);
        }